APUE------进程环境

来源:互联网 发布:mmd极乐净土镜头数据 编辑:程序博客网 时间:2024/06/08 04:06

mian函数

C程序总是从main函数开始执行。main函数的原型是:
int main(int argc, char *argv[]);
其中,argc是命令行参数的数目,argv是指向参数的各个指针所构成的数组。

当内核执行C程序时,在调用main之前先调用一个特殊的启动例程。可执行程序文件将此启动例程指定为程序的起始地址——这是由链接编辑器设置的,而连接编辑器则由C编译器调用。启动例程从内核取得命令行参数和环境变量值,然后为按上述方式调用mian函数做好安排。

进程终止

有8中方式使进程终止,其中5种为正常终止,它们是:
1. 从main返回;
2. 调用exit;
3. 调用_exit或_EXIT;
4. 最后一个线程从启动例程返回;
5. 从最后一个线程调用pthread_exit。

异常终止有3种方式,它们是:
6. 调用abort;
7. 接到一个信号;
8. 最后一个线程对取消请求做出响应。

退出函数
#include <stdio.h>void exit(int status);void _EXIT(int status);#include <unistd.h>void _exit(int status);

exit函数总是执行一个标准I/O库的清理关闭操作。
3个退出函数都带一个整型参数,称为终止状态。大多数UNIX系统shell都提供检查进程终止状态的方法。

如果(a)调用这些函数时不带终止状态,或(b)main执行了一个无返回值的return语句,或(c)main没有声明返回类型为整型,则该进程的终止状态是未定义的。但是,若main的返回类型是整型,并且main执行到最后一条语句时返回,那么该进程的终止状态是0;

函数atexit

按照ISO C规定,一个进程可以登记多至32个函数,这些函数将有exit自动调用。我们成为这些函数为终止处理程序,并调用atexit函数来登记

#include <stdlib.h>int atexit(void (*func)(void));//返回值:若成功,返回0;若出错,返回非0

其中,atexit的参数是一个函数地址,当调用此函数时无需向它传递任何参数,也不期望它会返回一个值。exit调用这些函数的顺序与它们登记的顺序是相反的。同一函数若被登记多次,也会被调用多次。

exit首先调用各终止处理程序,然后关闭所有打开流。

命令行参数

当执行一个程序时,调用exec的进程可以将命令行参数传递给该新程序。

环境表

每个程序都接受到一张环境表。与参数表一样,环境表也是一个字符指针数组,其中每个指针包含一个以null结束的C字符串的地址。全局变量environ则包含了该指针数组的地址:
extern char **environ;

我们称environ为环境指针,指针数组为环境表,其中各指针指向的字符串为环境字符串

C程序的存储空间布局

历史沿袭至今,C程序一直由下列几部分组成:
1. 正文段。这是由CPU执行的机器指令部分。通常正文段是可共享的。
2. 初始化数据段。通常将此段称为数据段,它包含了程序中需明确地赋初值的变量。
3. 未初始化数据段。通常将此段称为bss段,这一名称来源于早期汇编程序一个操作符,在程序开始执行之前,内核将此段中的数据初始化为0或空指针。
4. 栈。自动变量以及每次函数调用时所需保存的信息都存放在此段中。每次函数调用时,其返回地址以及调用者的环境信息都存放在栈中。然后,最近被调用的函数在栈上为其自动和临时变量分配存储空间。通过以这种方式使用栈,C递归函数可以工作。
5. 堆。通常在堆中进行动态存储分配。由于历史上形成的惯例,堆位于未初始化数据段和栈之间。

存储空间分配

ISO C 说明了3个用于存储空间动态分配的函数。
1. malloc,分配指定字节数的存储区。此存储区中的初始值不确定。
2. calloc,为指定数量指定长度的对象分配存储空间。该空间中的每一位都初始化为0
3. realloc,增加或减少以前分配区的长度。

#include <stdlib.h>void *malloc(zise_t size);void *calloc(size_t nobj, size_t size);void *realloc(void *ptr, size_t newsize);//3个函数返回值:若成功,返回非空指针;若出错,返回NULLvoid free(void *ptr);

环境变量

ISO C定义了一个函数getenv,可以用其取环境变量值,但是该标准又称环境的内容是由实现定义的。

#include <stdlib.h>char *getenv(const char *name);//返回值:指向与name关联的value的指针;若未找到,返回NULL

注意,此函数返回一个指针,它指向name = value 字符串中的value。我们应当使用getenv从环境中取一个指定环境变量的值,而不是直接访问environ。

除了获取环境变量值,有时也需要设置环境变量。

#include <stdlib.h>int putenv(char *str);//函数返回值:若成功,返回0;若出错,返回非0int setenv(const char *name, const char *value, int rewrite);int unsetenv(const char *name);//两个函数返回值:若成功,返回0;若出错,返回-1

putenv取形式为name = value的字符串,将其放到环境表中。如果name已经存在,则先删除其原来的定义。
setenv将name设置为value。如果在环境中name已经存在,那么(a)若rewrite非0,则首先删除其现有的定义;(b)若rewrite为0,则不删除现有的定义。
unsetenv删除name的定义。

函数setjmp和longjmp

跳转功能函数

#include <setjmp.h>int setjmp(jmp_buf env);//返回值:若直接调用,返回0;若从longjmp返回,则为非0void longjmp(jmp_buf env, int val);

在希望返回到的位置调用setjmp。参数env的类型是一个特殊类型jmp_buf。这一数据类型是某种形式的数组,其中存放在调用longjmp时能用来恢复栈状态的所有信息。因为需在另一个函数中引用env变量,所以通常将env变量定义为全局变量。

#include "apue.h"#include <setjmp.h>#define TOK_ADD 5jmp_buf jmpbuffer;int main(void){    char line[MAXLINE];    if(setjmp(jmpbuffer) != 0)        printf("error");    while(fgets(line, MAXLINE. stdin) != NULL)        do_line(line);    exit(0);    void cmd_add(void)    {        int token;        token = get_token();        if(token < 0)            longjmp(jmpbuffer, 1);    }}

函数getrlimit和setrlimit

每个进程都有一组资源限制,其中一些可以用getrlimit和setrlimit函数查询和更改。

#include <sys/resource.h>int getrlimit(int resource, struct rlimit *rlptr);int setrlimit(int resource, const struct rlimit *rlptr);//两个函数返回值:若成功,返回0;若出错,返回非0

对这两个函数的每一次调用都指定一个资源以及一个指向下列结构的指针。

struct rlimit{    rlim_t rlim_cur;    rlim_t rlim_max;};

在更改资源限制时,须遵守下列3条规则。
1. 任何一个进程都可将一个软限制值更改为小于或等于其硬限制值。
2. 任何一个进程都可降低其硬限制值,但它必须大于或等于其软限制值。
3. 只有超级用户进程可以提高硬限制值。

至于资源。自行百度。

0 0
原创粉丝点击