现在的位置: 首页 > 综合 > 正文

AUPE学习第七章——进程环境

2014年01月05日 ⁄ 综合 ⁄ 共 4060字 ⁄ 字号 评论关闭

7.2main函数

c程序总是从main函数开始执行。main函数的原型:
int   main(int   argc,  char  *argv[ ])
在执行main函数之前,先要调用一个启动例程。可执行文件将此启动例程指定为程序的起始地址。

7.3进程终止

进程有八种终止方式,五个正常终止,三个非正常终止。
正常:
从main返回、调用exit、调用_exit或者_Exit、最后一个线程从其启动例程返回、最后一个线程调用pthread_exit。
非正常:
调用abort、接到一个信号并终止、最后一个线程对取消请求作出响应。
启动例程如果用c语言的格式表示的话。如下:
exit(main(argc,  argv))
但是启动例程实际上是汇编语言编写的。
我们可以用下面三个函数正常终止一个程序:
void    exit(int   status)
vpod   _Exit(omt   status)
void    _exit( int  status)
按照ISO C的规定,一个进程可以登记多达32个函数,这些函数将由exit自动调用。并调用atexit函数来登记这些函数。
int   atexit(void    (*func)( void))
成功返回0,不成功返回非0值。
它的参数是一个函数地址,调用参数函数时不用向其传递任何参数。
下面的程序是atexit函数案例:
atexittest.c:
#include "apue.h"
static void  my_exit1(void);
static void  my_exit2(void);
int main(void)
{
        if (atexit(my_exit2) != 0)
                err_sys("can't register my_exit2");
        if (atexit(my_exit1) != 0)
                err_sys("can't register my_exit1");
        if (atexit(my_exit1) != 0)
                err_sys("can't register my_exit1");
        printf("main is done\n");
        return(0);
}
static void my_exit1(void)
{
        printf("first exit handler\n");
}
static void my_exit2(void)
{
        printf("second exit handler\n");
}

运行结果:
[root@localhost apue]# vim atexittest.c
[root@localhost apue]# gcc atexittest.c 
[root@localhost apue]# ./a.out 
main is done
first exit handler
first exit handler
second exit handler

7.4命令行参数

当执行一个程序时,调用exec的进程可以将命令行参数传递给该更新程序。
标准要求将argv[argc]设置成一个空指针。
argvtest.c:
#include "apue.h"
int main(int argc, char *argv[])
{
        int i;
        for (i = 0; argv[i] != NULL; i++)
                printf("argv[%d]: %s\n", i, argv[i]);
        exit(0);
}

运行结果:

[root@localhost apue]# vim argvtest.c
[root@localhost apue]# gcc argvtest.c 
[root@localhost apue]# ./a
access.out  a.out       apue.h      
[root@localhost apue]# ./a.out nihao huang chengdu
argv[0]: ./a.out
argv[1]: nihao
argv[2]: huang
argv[3]: chengdu

7.8存储器分配

ISO C说明了三个用于存储器空间动态分配的函数:

malloc。分配指定字节数的存储区,此存储区的初始值不确定。
calloc。为指定数量的具有指定长度的对象分配存储空间。
realloc。更改以前分配区的长度。
void    *malloc(  size_t   size)
void    *calloc(  size_t   nobj,   size_t  size)
void    *realloc(  void  *ptr,   size_t   newsize)
我们可以通过sbrk系统调用来实现对进程的空间的增加或者缩小。
用malloc的常见错误有指针没有初始化、指针用完以后没有调用free函数释放内存,到时内存泄露。

7.9环境变量

环境字符串的形式是:
name = value;
ISO C定义了一个函数getenv,可以用其取环境变量值。
char  *getenv(  const   char   *name)
返回值是指向与name关联的value的指针,如果没有找到则返回NULL。
我们可以通过下面三个函数来设置环境变量的值或者删除,新添加环境变量。
int   putenv(  char  *str)   //添加
int   setenv( const  char   *name,   const   char  *value,   int   rewrite)  //设置更改
int   unsetenv(const   char   *name)                          //删除

7.10 setjmp和longjmp函数

这两个函数实现不同函数之间的跳转,setjmp和longjmp。
他们用于在深层次的函数中出现错误后 ,返回到当前函数调用路径上的某个函数中。
int   setjmp(  jmp_buf   env)   //直接调用返回0,从longjmp返回则返回非0值。
int   longjmp(  jmp_buf  env,  int   val)
下面的实例是两个函数的应用:
setjmptest.c:
#include "apue.h"
#include <setjmp.h>

#define  TOK_ADD  5

jmp_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);
}

在setjmp中,如果编译用优化模式的话,则局部变量和易失变量(register)不能保存,用关键字volatile保存的局部变量可以保存。

longjmptest.c:
#include "apue.h"
#include <setjmp.h>

static void f1(int, int, int, int);
static void f2(void);
static jmp_buf jmpbuffer;
static int globval = 1;

int main(void)
{
        int autoval = 2;
        register int regival = 3;
        volatile int volaval = 4;
        static int statval = 5;
        if (setjmp(jmpbuffer) != 0)
        {
                printf("after longjmp:\n");
                printf("globval = %d, autoval = %d, regival = %d, volaval = %d," 
                " statval = %d\n", globval, autoval, regival, volaval, statval);
                exit(0);
        }
        globval = 95;
        autoval = 96;
        regival = 97;
        volaval = 98;
        statval = 99;
        f1(autoval, regival, volaval, statval);
        exit(0);
}
static void f1(int i, int j, int k,int l)
{
                printf("in f1():\n");
                printf("globval = %d, autoval = %d, regival = %d, volaval = %d," 
                " statval = %d\n", globval, i, j, k, l);

        f2();
}
static void f2(void)
{
        longjmp(jmpbuffer, 1);
}
运行结果:
[root@localhost apue]# vim longjmptest.c
[root@localhost apue]# gcc longjmptest.c 
[root@localhost apue]# ./a.out 
in f1():
globval = 95, autoval = 96, regival = 97, volaval = 98, statval = 99
after longjmp:
globval = 95, autoval = 96, regival = 97, volaval = 98, statval = 99
[root@localhost apue]# gcc  -O longjmptest.c 
[root@localhost apue]# ./a.out 
in f1():
globval = 95, autoval = 96, regival = 97, volaval = 98, statval = 99
after longjmp:
globval = 95, autoval = 2, regival = 3, volaval = 98, statval = 99

7.11getrlimit和setrlimit函数

每个进程都有资源限制,我们可以通过getrlimit和setrlimit函数来实现对这些限制的查询和更改。

int   getrlimit(int  resource,   struct  rlimit   *rlptr)
int   setrlimit(int  resource,   const struct  rlimit  *rlptr)
对着两个函数的每一次调用都会指定一个资源以及一个指向下列结构的指针。
struct  rlimit{
rlim_t   rlim_cur;
rlim_t   rlim_max;
}

抱歉!评论已关闭.