Chinaunix首页 | 论坛 | 博客
  • 博客访问: 316721
  • 博文数量: 79
  • 博客积分: 1480
  • 博客等级: 上尉
  • 技术积分: 848
  • 用 户 组: 普通用户
  • 注册时间: 2009-06-11 15:29
文章分类

全部博文(79)

文章存档

2012年(1)

2011年(5)

2010年(19)

2009年(54)

我的朋友

分类: C/C++

2009-09-16 15:22:38

1、wait和waitpid函数
   #include
   pid_t wait(int *statloc);
   pid_t waitpid(pid_t pid, int *statloc, int options);
注1:不管子进程正常还是异常终止,内核都会给父进程发送SIGCHLD
    信号,默认父进程是忽略该信号
注2:wait可以block调用者直到子进程结束,而waitpid有一个选
    项让调用者不被block,它不会等子进程首先结束,而是利用选
    项控制等待哪个进程
注3:如果调用者block并且有很多子进程,那么只要有一个子进程结
    束wait立即返回,并且可以根据返回的ID得知哪个子进程结束
注4:指针指向终止进程的终止状态,NULL表示不想关心,该整数的
     一些bits表示exit状态(正常退出),一些bits表示signal
     number(异常退出),有1bit表示是否生成了core文件
     可以通过以下宏来获取程序是怎样退出的,true or false
     #include
     WIFEXITED(status) ;
     //获取子进程传递给exit参数的低8位,正常结束
     WIFSIGNALED(status)
     //获取异常终止的signal number
     WCOREDUMP(status);
     //进程终止是否生成core文件
     WIFSTOPPED(status);
     //若子进程stopped,则为true,可以用WSTOPSIG获取让子
     //进程stop的signal number
     WIFCONTINUED(status);
     //若子进程在job control stop之后已continue,则为
     // true

注5:pid参数
    pid == -1 等待任何子进程,waitpid等同于wait
    pid > 0   等待ID等于pid的子进程
    pid == 0  等待任何子进程,其进程group ID与调用进程一
              样
    pid < -1  等待任何子进程,其进程group ID等于正pid值
注6:options参数
    WNOHANG   nonblocking版本的wait
    WCONTINUED
    WUNTRACED 这2支持 JOB CONTROL
2、#include
   #include
   #include
   #include
   pid_t wait3(int *statloc, int options, struct
               rusage *rusage);
   pid_t wait4(pid_t pid, int *statloc, int options,
               struct rusage *rusage);
注1:struct rusage
    终止进程使用的资源概况:使用的user CPU time, system
    CPU time, page fault数量,接受到的singal数量等等
    和它所有的子进程

3、Race Conditions
注1:若想等待子进程结束,就必须调用wait函数系列中的一个,若
    想等待父进程结束,可以使用
    while ((getppid() != 1)
           sleep(1);//waste CPU time, every 1 second
注2:设想的一种互相通讯的方式
    TELL_WAIT();
    //set things up for TELL_xxx & WAIT_xxx
    /*
     * child process
     */
    TELL_PARENT(getppid()); //tell parent we are done
    WAIT_PARENT();          // and wait parent
    /*
     * parent process
     */
    TELL_CHILD(pid)         //tell child we are done
    WAIT_CHILD();           // and wait for child

4、exec函数
   #include
   int execl(const char *pathname, const char *arg0,
             ... /* (char *)0 */);
   int execv(const char *pathname, char *const argv[]
             );
   int execle(const char *pathname, const char *arg0,
           ... /* (char *)0, char *const envp[] */);
   int execve(const char *pathname, char *const
              argv[],char *const envp[]);
   int execlp(const char *filename, const char *arg0,
              .../* (char *)0 */);
   int execvp(const char *filename, char *const
              argv[]);
   (-1 on error, no return on success)
 Function pathname
filename
  Arg list
argv[]
  environ
envp[]
                 
 execl  .      .      .  
 execlp    .    .      .  
 execle  .      .       .
 execv  .        .    .  
 execvp    .      .    .  
 execve  .        .      .
 letter    p    l  v      e
Tab.1 Difference among six exec functions

Fig.1 Relationship of the six exec funcions
注1:调用exec函数之后,进程完全被新程序替代,从新程序的main
    函数开始执行;但进程ID不改变,因为并没有新建一个进程,只
    是从磁盘上读取了新程序,填充到当前进程的text,data,
    heap,stack
注2:使用fork()可以创建一个新进程;使用exec可以开始一个新程
     序
注3:envp[]  传递环境变量字符串数组
    environ 拷贝当前进程的环境变量给新程序
    Arg list 由ARG_MAX(resouce limit)限制
注4:exec几乎继承了调用进程的所有属性甚至包括file locks
    file mode creation mask, process signal mask,
    pending singals, resouce limits
注5:进程里每个打开的文件描述符(fd)都有一个close_on_exec标
    志,若设置了,则描述符会在exec中关闭,默认还是开启的;
    但POSIX.1特别说明了要求open directory streams
    (opendir)在exec过程中关闭
注5:跟子进程继承不同的是,effective user ID可能在这过程中
    改变,得看执行程序文件的set-user-ID和set-group-ID位
注6:只有execve是系统调用函数,其他5个都是库函数

5、Changing User IDs and Group IDs
   #include
   int setuid(uid_t uid);
   int setgid(gid_t gid);
   (0 if OK, -1 on error)
注1:若进程有超级用户权限,那么setuid将real/effective/
     saved set-user-ID都设置成uid
     若进程没有超级用户权限,那么setuid只将effective user
     ID设置成uid,其他2个不变
     若前2个条件都不满足,errno会设为EPERM,返回-1
注2:只有超级用户进程可以改变real user ID。一般,real
     user ID在登录的时候被login程序设置,且不改变
    saved set-user-ID在exec过程中从effective ID拷贝
   #include
   int setreuid(uid_t ruid, uid_t euid);
   int setregid(gid_t rgid, gid_t egid);
   (0 if OK, -1 on error,交换real和effective ID)
   int seteuid(uid_t uid);
   int setegid(gid_t gid);
   (0 if OK, -1 on error,只有effective ID改变)

Fig.2 Summary of all the funcitons that set the various user IDs


      


阅读(700) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~