【APUE】进程控制

本文介绍进程控制,包括创建进程,执行程序和进程终止

1.进程标识符

    每一个进程都有一个非负整数表示的唯一进程ID,pid。虽然pid是唯一的,但是可以重复使用,当进程结束的时候,
    其pid就可以在次使用了。
    系统中常有一些专用进程:
    0:通常是调度进程,常称为交换进程,因为不使用磁盘中的任何程序,所以又称为系统进程。
    1:通常是init进程
    下面的函数返回进程标识符
    #include <unistd.h>
    pid_t getpid(void);
    //返回调用进程的pid
    pit_t getppid(void);
    //返回调用进程的父进程pid
    uid_t getuid(void);
    //返回调用进程的实际用户id
    uid_t geteuid(void);
    //返回调用进程的有效用户id
    gid_t getgid(void);
    //返回调用进程的实际组id
    gid_t getegid(void);
    //返回调用进程的有效组id

2.fork函数

    创建一个新进程
    #include <unistd.h>
    pid_t fork(void);
    //子进程中返回0,父进程返回子进程pid,出错返回-1
    子进程是父进程的副本,子进程获得父进程的数据空间,堆和栈的副本,父子之间不共享这些存储区部分
    父子进程共享正文段,而正文段通常是只读的。也就是说对子进程进行操作,对父进程没有任何影响。
    (现代的处理方法:使用到了写时复制的技术,存储区内容父子共享,并为只读,当父子进程中任一要去写的时候,
    内核就为其修改的那个部分制作一个副本,通常是虚拟存储器系统的一页)

3.vfork函数


    创建一个进程,但是与fork有区别
    #include <unistd.h>
    pid_t vfork(void);
    //子进程中返回0,父进程返回子进程pid,出错返回-1
    此时,子进程和父进程共享资源,当对子进程进行操作的时候,会影响到父进程。vfork之后通常接着exec。
    vfork保证子进程先运行,他在调用了exec或者exit之后父进程才能被调度运行。

4.exit函数

    在说明fork函数时,显而易见,子进程是在父进程内调用fork后生成的。子进程在终止的时候会将把自己的终止状态
    返回给父进程。如果父进程在子进程终止之前终止,对于父进程的所有子进程他们的父进程都改为init进程。我们称
    这些进程由init领养。其操作的大体过程如下:
        在一个进程终止的时候,内核逐个检查所有活动进程,以判断它是否是正要终止进程的子进程。如果是,
        则将该进程的父进程ID更改为1.这种处理方式保证了每个进程都有一个父进程。
    如果子进程在父进程之前终止,内核就为每个终止子进程保存了一定量的信息,所以当终止进程的父进程调用wait
    或waitpid时,可以得到这些信息。这些信息至少包括进程ID,进程的终止状态,以及该进程使用的CPU时间总量。
    内核可以释放终止进程所使用的所有存储区,关闭其所有的打开文件。但是一个已经终止,而父进程尚未对其进行
    善后处理的进程被称之为僵死进程。
    当init的子进程终止的时候,init进程会自动调用wait函数取得其终止状态。防止了系统中有很多僵死进程。

5.wait和waitpid函数

    当调用这两个函数的时候:
        如果其所有子进程都还在运行,则阻塞;
        如果一个子进程已经终止,正等待父进程获取其终止状态,则取得该子进程的终止状态立即返回;
        如果没有任何子进程,则会出错.
    #include <sys/wait.h>
    pit_t wait(int *statloc);
    pit_t waitpid(pid_t pid, int *statloc, int options);
    在一个子进程终止前,wait使其调用者阻塞,而waitpid有一个选项,可以使调用者不阻塞。
    waitpid并不等待在其调用之后的第一个终止子进程,它有若干个选项,可以控制它所等待的进程。
    如果第一个子进程已经终止,并且是一个僵死的进程,wait立即返回并取得该子进程的状态,否则wait使其调用者阻塞
    直到一个子进程终止。若调用者阻塞而且它有多个子进程,则当有一个子进程终止的时候,wait函数就立即返回。
    statloc是一个整型指针,如果这个指针不为空,则存储子进程的状态
    pid参数的作用如下:
    pid == -1    等待任一子进程,此时,与wait等效
    pid > 0        等待其进程ID与pid相等的子进程
    pid == 0    等待其组ID等于调用进程组ID的任一子进程
    pid < -1    等待其组ID等于pid绝对值的任一子进程
    options参数使我们能进一步控制waitpid操作,此参数可以为0
    常量        说明
    WCONTINUED    若实现支持作业控制,那么由pid指定的任一子进程在暂停后已经继续,但其状态尚未报告,
            则返回其状态
    WNOHANG        若由pid指定的子进程并不是立即可用的,则waitpid不阻塞,此时其返回值为0
    WUNRTACEO    若某实现支持作业控制,而由pid指定的任一子进程已处于暂停状态,并且其状态自暂停以来
            还未报告过,则返回其状态。WIFSTOPPED宏确定返回值是否对应于一个暂停子进程

6.waitid函数

    此函数类似与waitpid,但是提供了更多的灵活性
    #include <sys/wait.h>
    int waitid(idtype_t idtype, id_t id, siginfo_t *infop, int options);
    //成功返回0,出错返回-1
    使用单独的参数表示要等待的子进程类型id的值与idtype的值有关,以下列出idtype的类型:
        P_PID    等待一个特定的进程,id包含要等待进程的进程id
        P_PGID    等待一个特定进程组的任一子进程,id包含等待进程组的进程组id
        P_ALL    等待任意子进程,乎略id
    options参数:
        WCONTINUED    等待一个进程,它以前曾被暂停,此后有继续执行,但其状态未返回
        WEXITED        等待已经退出的进程
        WNOHANG        如无可用的子进程退出状态,立即返回而非阻塞
        WNOWAIT        不破坏进程退出状态。该子进程退出状态后可由后续的wait,waitpid或waitid调用获取
        WSTOPPED    等待一个进程,它已经暂停,但其状态尚未报告

7.竞争条件

    当多个进程都企图对共享数据进行某种处理,而最后的结果由取决于进程运行顺序的时候,我们认为发生了竞争

8.exec函数

    当进程调用exec函数的时候,进程执行的程序完全替换为新的程序,而新程序从其main函数开始执行。
    exec函数只是用一个全新的程序替换了当前进程的正文,数据,堆和栈段。
    #include <unistd.h>
    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,成功不返回
    前4个函数将路径名作为参数,后两个函数将文件名作为参数,如果filename含有/,则表示路径名
    否则就按照环境变量所指定的目录中搜索可执行文件
    execlp和execvp的filename可以是shell脚本
    其他参数为新程序的命令行参数
    6个函数中,字母p表示该函数取filename为参数,字母l表示该函数取一个参数表,与字母v互斥,v表示该函数取一个envp[]数组,而不使用当前环境

9.更改用户ID和组ID


    #include <unistd.h>
    int setuid(uid_t uid);
    int setgid(gid_t gid);
    //成功返回0,出错返回-1
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值