`

UNIX环境高级编程 进程控制

 
阅读更多

 

 

相关函数列表

//下列函数返回一个进程的标识符
#include <unistd.h>
pid_t getpid(void);
pid_t getppid(void);
uid_t getuid(void);
uid_t geteuid(void);
gid_t getgid(void);
gid_t getegid(void);

//创建新进程
#include <unistd.h>
pid_t fork(void);
pid_t vfork(void);


//当一个进程正常或异常终止时,内核就向其父进程发送SIGCHLD信号,wait或waitpid的进程会
//1.如果其所有子进程都还在运行则阻塞
//2.如果一个子进程已停止,正等待父进程获取其终止状态,则取得该子进程的终止状态立即返回
//3.如果它没有任何子进程,则立即出错返回
//两个函数的区别
//1.在一个子进程终止前,wait使其调用者阻塞,而waitpid有一选项,可使调用者不阻塞
//2.waitpid并不等待在其调用之后的第一个终止子进程,它有若干个选项,可以控制它所等待的进程
#include <sys/wait.h>
pid_t wait(int *statloc);
pid_t waitpid(pid_t pid, int *statloc, int options);

//Single UNIX Specification包括了另一个取得进程终止状态的函数--waitid,此函数类似于waitpid
#include <sys/wait.h>
int waitid(idtype_t idtype, id_t id, siginfo_t *infop, int options);

//大多数UNIX系统实现提供了另外两个函数,这两个函数是从UNIX系统BSD分支延袭下来的
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/time.h>
#include <sys/resource.h>
pid_t wait3(int *statloc, int options, struct rusage *rusage);
pid_t wait4(pid_t pid, int *statloc, int options, struct rusage *rusage)


//fork函数创建新进程,用exec可以初始执行新的程序,exit函数和wait函数处理终止和等待终止
//函数exec系列,一共有7个,这些函数的区别
//1.前4个函数是用路径做参数,后两个用文件名,最后一个用文件描述符
//2.与参数传递有关,(l表示list,v表示矢量vector),函数execl,execlp和execle要求将新程序的
//  每个命令参数都说明一个单独的参数。另外四个函数(execv,execvp,execve,fexecve)则应先
//  构造一个指向各参数的指针数组,然后将数组作为参数
//3.与新程序传递环境表相关,以e结尾的三个函数(execle,execve和fexecve)可以传递一个指向环境
//  字符串指针数组。其他4个函数则使用调用进程中的environ变量为新程序复制现有的环境
#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[]);
int fexecve(int fd, char *const argv[], char *const envp[]);


//设置实际用户ID和有效用户ID
#include <unistd.h>
int setuid(uid_t uid);
int setgid(gid_t gid);

//历史上BSD支持下列函数,其功能是交换实际用户ID和有效用户ID的值
#include <unistd.h>
int setreuid(uid_t ruid, uid_t euid);
int setregid(gid_t rgid, gid_t egid);

//POIX.1包含的两个函数类似于setuid和setgid,但只更改有效用户ID和有效组ID
#include <unistd.h>
int seteuid(uid_t uid);
int setegid(gid_t gid);


//下面函数用来在程序中执行一个命令字符串,因为system实际调用了fork,exec和waitpid,因此有
//三种返回值
//1.for失败或者waitpid返回除EINTR之外的出错,则system返回-1,并且设置errno以指示错误类型
//2.如果exec失败(表示不能执行shell),则其返回值如同shell执行了exit(127)一样
//3.柔则所有3个函数(fork,exec和waitpd)都成功,那么system的返回值是shell的终止状态
#include <stdlib.h>
int system(const char *cmdstring);


//进程会计,每个系统实现不同,但是基本结构如下
#include <sys/acct.h>
typedef u_short comp_t;
struct acct {
    char ac_flag;      //flag
    char ac_stat;      //termination status
    uid_t ac_uid;      //real user ID
    gid_t ac_gid;      //read group ID
    dev_t ac_tty;      //controlling terminal
    time_t ac_btime;   //starting calendar time
    comp_t ac_utime;   //user CPU time
    comp_t ac_stime;   //system CPU time
    comp_t ac_etime;   //elapsed time
    comp_t ac_mem;     //average memory usage
    comp_t ac_io;      //bytes transferred(read and write)
    comp_t ac_rw;      //blocks on BSD system
    char ac_comm[8];   //command name
};


//一个用户可能有多个登陆名,系统会记录用户登陆时的名字,下面函数可以获取
#include <unistd.h>
char *getlogin(void);

//可以用nic函数获取和更改它的nic值,这个函数只能影响到自己的nice值,不能影响任何其他进程的
//nice值
#include <unistd.h>
int nice(int incr);

//下面函数可以像nice一样获得进程的nice值,而且还可以获得一组相关进程的nice值
//which值可以取以下三个值之一:
//1.PRIO_PROCESS表示进程
//2.PRIO_PGRP表示进程组
//3.PRIO_USER表示用户ID
#include <sys/resource.h>
int getpriority(int which, id_t who);

//下面函数可用于为进程,进程组和属于特定用户ID的所有进程设置优先级
#include <sys/resource.h>
int setpriority(int which, id_t who, int value);

//任何一个进程都可以调用下面函数获得它自己的系统CPU时间,用户CPU时间,以及子进程的系统CPU
//时间,子进程的用户CPU时间
#include <sys/times.h>
clock_t times(struct tms *buf);
//tms结构体如下
struct tms {
    clock_t tms_utimes;      //user cpu time
    clock_t tms_stime;       //system cpu time
    clock_t tms_cutime;      //user cpu time,terminated children
    clock_t tms_cstime;      //system cpu time,terminated children
};

 

 

fork函数

其创建新进程为子进程,fork函数被调用一次,但是返回两次。

子进程返回的是0

父进程返回的是子进程的进程ID

子进程和父进程继续执行fork之后的指令,子进程是父进程的副本,列如子进程获得父进程数据空间,堆和栈 

的副本(注意是子进程所拥有的副本)。父进程和子进程并不共享这些存储空间部分,父进程和子进程共享正文段。

返回子进程ID的原因是一个进程可以有多个子进程,但是没有函数可以获得所有子进程的ID,而父进程只有一个可以通过函数getppid()获得

fork之后是父进程先执行还是子进程先执行是不确定的,取决于操作系统的调度,如果要求父进程和子进程之间相互同步,则要求某种形式的进程间通信。

父进程和子进程共享相同的文件描述符

 

fork之后父进程和子进程之间对打开文件的共享


 

 

在fork之后处理文件描述符有以下两种情况

1)父进程等待子进程完成,在这种情况下,父进程无需对其描述符做任何处理。当子进程终止后,它曾进行过读,写操作的任一共享描述符的文件偏移量已做了相应的更新

2)父进程和子进程各自执行不同的程序段,这种情况下,在fork之后,父进程和子进程各自关闭他们不需要使用的文件描述符,这样就不会干扰对方使用的文件描述符,这种方法是网络服务器进程经常使用的

 

fork有以下两种用法

1)一个父进程希望复制自己,使父进程和子进程同时执行不同的代码段,这在网络服务进程中是常见的--父进程等待客户度端的服务请求,当请求到来时父进程调用fork使子进程处理此请求,父进程继续等待下一个请求

2)一个进程要执行一个不同的程序,这对shell是常见的,在这种情况下,子进程从fork返回后立即调用exec

 

fork和vfork的区别

1)子进程并不将父进程的地址空间完全复制到子进程中,因为子进程会立即调用exec,这种优提高了效率

2)vfork保证子进程优先运行,在它调用exec或exit之后父进程才可能被调度运行,当子进程调用这两个函数中的任意一个时,父进程会恢复运行。

 

 

进程有5种正常终止及3种异常终止方式

1)在main函数内执行return语句

2)调用exit函数

3)调用_exit或_Exit函数

4)进程的最后一个线程在其启动例程中执行return语句

5)进程的最后一个线程调用pthread_exit函数

 

3种异常终止具体如下

1)调用abort,产生SIGABRT信号,这是下一种异常终止的一种特列

2)当进程接收到某些信号时,信号可由进程自身(如调用abort函数),其他进程或内核产生

3)最后一个线程对"取消"(cancellation)请求作出响应

所有子进程退出后,将终止状态返回给父进程,如果父进程已经退出,则将父进程改为init进程

一个已经终止,但是其父进程尚未对其进行善后处理(获取终止子进程的有关信息,释放他仍占用的资源)的

进程被称为 僵死进程(zombie)

 

 

检查wait和waitpid锁返回的终止状态的宏

说明
 WIFEXITED(status)

若为正常终止子进程返回的状态,则为真。对于这种情况可执行WEXITSTATUS(

status),获取子进程传给exit或_exit参数的低8位

WIFSIGNALED(status)

若为异常终止进程返回的状态,则为真(接到一个不捕捉的信号),对于这种情况,

可执行WTERMSIG(status),获取使子进程终止的信号编号。另外,有些实现

(非Single UNIX Specification)定义宏WCOREDUMP(status),若已产生终止进程

的core文件,则它返回真

WIFSTOPPED(status)

若为当前暂停子进程的返回的状态,则为真。对于这种情况,可执行

WSTOPSIG(status),获取使子进程暂停的信号编号

WIFCONTINUED(status)

若在作业控制暂停后已继续的子进程返回了状态,则为真(POSIX.1的XSI扩展,

仅用于waitpid)

 

waitpid的options常量

常量 说明
WCONTINUED

若是先支持作业控制,那么由id指定的任一子进程在停止后已经继续,但其状态尚未

报告,则返回其状态(POSIX.1的XSI扩展)

WNOHANG 若由pid指定的子进程并不是立即可用的,则waitpid不阻塞,此时其返回值为0
WUNTRACED

若某是先支持作业控制,而由pid指定的任一子进程已处于停止状态,并且其状态自

停止以来还未报告过,则返回其状态。WIFSTOPPED宏确定返回值是否对应用与一个

停止的子进程

 

竞争条件

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

竞争条件(race condition)

 

7个exec函数之间的关系

函数 pathname filename fd 参数表 argv[] environ envp[]
execl        
execlp        
execle          
execv        
execvp        
execve          
fexecve        
名字中的字母   p f l v   e

  


 

 

 

 

解释器文件

现在所有的UNIX系统都支持解释器文件(interpreter file),它是文本文件

//形式是
#! pathname [optional-argument]

//比如
#! /bin/sh

pathname通常是绝对路径名,对它不进行什么特殊的处理(不适用PATH进行路径搜索)对这种文件的识别是由

内核作为exec系统调用处理的一部分来完成的。内核调用exec函数的进程世纪之星的并不是该解释器文件,而

是在该解释器文件第一行中 pathname所指定的文件。一定要将解释器文件(文本文件,它以 #! 开头)和解释器

(由该解释器我呢间第一行中的pathname指定)区分开来

比如一段程序调用一个解释器

cat /home/sar/bin/testinterp
#! /home/sar/bin/echoarg foo

//这里echoarg是一段程序,echoarg又exec了testinterp并传入了一些参数
//执行结果
//第一个打印的是解释器的pathname,然后是参数
//接着是解释器执行后调用的命令和命令参数
./a.out  
argv[0]: /home/sar/bin/echoarg
argv[1]: foo
argv[2]: /home/sar/bin/testinterp
argv[3]: myarg1
argv[4]: MY ARG2

  

 

 

进程会计

大多数UNIX系统提供了一个选项以进程会计(process accounting)处理。启动该选项后,每当进程结束时内核

就会写一个会计记录。典型的会计记录包含总量较小的二进制数据,一般包括命令名,所使用的CPU时间

总量,用户ID和组ID,启动时间等

函数acct启动和禁用进程会计,唯一使用这个函数的命是accton。root执行一个带路径名参数的通常是

/var/account/acct。  在linux中该文件是/var/account/pacct

会计记录结果定义在<sys/acct.h>中

 

进程会计,结构体,会计记录所需的各个数据 (CPU时间,传递的字符数等)都由内核保存在进程表中,并在一个新进程被创建时初始化(如在fork之后在子进程中)。进程终止时写一个会计记录

1.我们不能获取永不终止的进程会计记录,如init进程

2.会计文件记录的顺序对应于进程终止的顺序,而不是他们的启动顺序,为了确定启动顺序需要读全部的会计文件,并按照启动日历时间排序,但这样并不能保证完全精确

 

会计记录中的ac_flag值

ac_flag 说明
AFORK 进程是由fork产生的,但从未调用exec
ASU 进程使用超级用户特权
ACCORE 进程转存core
AXSIG 进程由一个信号杀死
AEXPND 扩展的会计条目
ANVER 新格式记录

 

 

 

参考

实际用户ID,有效用户ID及设置用户ID

什么是实际用户ID、有效用户ID和设置用户ID

一个fork的谜题

 

 

  • 大小: 27.9 KB
  • 大小: 79.4 KB
分享到:
评论

相关推荐

    UNIX环境高级编程-pdf

    《UNIX环境高级编程》详细解释了信号的概念、发送、接收和处理,以及信号在进程控制中的应用,帮助读者理解如何优雅地处理程序中断和异常情况。 此外,书中还涉及了进程环境、系统调用接口、编译和链接、动态装载、...

    UNIX环境高级编程

    《UNIX环境高级编程》是一本深入探讨UNIX系统编程的权威参考书籍。它涵盖了UNIX编程的各个方面,从基础的UNIX系统结构和原理,到文件操作、进程控制、进程间通信、多线程编程、网络编程以及终端I/O和伪终端等内容。...

    UNIX环境高级编程.pdf

    ### UNIX环境高级编程知识点概述 #### 一、UNIX基础知识 **1.1 引言** 在计算机科学领域,操作系统作为连接硬件与软件的桥梁,为应用程序提供了必要的服务,包括但不限于执行新程序、打开文件、读取文件内容、...

    UNIX环境高级编程(中文第三版)高清完整

    《UNIX环境高级编程(第3版)》在保持前一版风格的基础上,根据最新的标准对内容进行了修订和增补,反映了最新的技术发展。书中除了介绍UNIX文件和目录、标准I/O库、系统数据文件和信息、进程环境、进程控制、进程关系...

    Unix环境高级编程中英文版包括源代码

    《Unix环境高级编程》是一本深受程序员和系统管理员喜爱的经典之作,主要涵盖了在Unix操作系统环境下进行高级编程的各种技术和方法。这本书分为多个章节,详细讲解了Unix系统接口、进程管理、文件系统、网络通信等...

    UNIX环境高级编程(PDF超清版)

    《UNIX环境高级编程》是一本深受程序员和系统管理员喜爱的经典之作,主要涵盖了在UNIX操作系统上进行高级编程的各种技术和实践。这本书以清晰的结构和深入的解释,为读者提供了丰富的UNIX编程知识,帮助他们掌握在这...

    Unix环境高级编程_UNIX环境高级编程_

    《Unix环境高级编程》是一本深入探讨Unix操作系统编程的经典之作,由W. Richard Stevens撰写,是许多计算机科学专业学生和专业开发者的必备参考书。这本书详细介绍了如何在Unix系统上进行系统级编程,包括文件I/O、...

    UNIX环境高级编程课后习题详细解答

    "UNIX环境高级编程"通常涵盖的主题包括进程管理、文件I/O、信号处理、网络编程、系统调用接口以及内存管理等。 课后习题往往旨在巩固和深化对这些概念的理解。以下是一些可能涉及的知识点: 1. **进程管理**:包括...

    UNIX环境高级编程(中文版)

    《UNIX环境高级编程》是一本深受程序员和系统管理员喜爱的经典之作,它由W. Richard Stevens撰写,对中国乃至全球的UNIX和Linux开发者具有深远影响。这本书深入浅出地讲解了在UNIX系统上进行程序开发的各种技术和...

    unix环境高级编程 第三版 文字版非扫码(带目录)

    ### Unix环境高级编程 第三版 知识点详解 #### 一、书籍概述与目标读者 《Unix环境高级编程》第三版是一本针对高级程序员和网络专业人士编写的实用参考书。该系列书籍由Addison-Wesley出版社创建于1990年,旨在为...

    unix环境高级编程pdf

    ### Unix环境高级编程知识点概述 #### 一、Unix基础知识概览 **1.1 引言** 本书聚焦于探讨Unix操作系统及其多种版本为程序提供的各项服务。这些服务包括但不限于执行新程序、文件操作(如打开、读取)、内存分配...

    unix环境高级编程1和unix网络编程.进程间通信2.rar

    《Unix环境高级编程》与《Unix网络编程:进程间通信》是两本在计算机科学领域具有深远影响力的经典著作。它们涵盖了Unix系统的核心概念和技术,对于理解操作系统原理、进行系统级编程以及深入研究网络通信有着不可...

    UNIX环境高级编程(中文第三版.zip

    《UNIX环境高级编程》是Unix系统编程领域的一本经典之作,被誉为“圣书”,对于学习Linux开发技术的人员来说,是一本不可或缺的参考书。这本书深入讲解了在Unix环境下进行系统级编程的各种技术和细节,涵盖了从基本...

    UNIX环境高级编程(第三版)-完整目录清晰版

    《UNIX环境高级编程》(第三版) 是一本深入讲解UNIX操作系统编程的经典著作,它由W. Richard Stevens撰写,是IT行业内广泛使用的参考资料。这本书详细介绍了如何在UNIX系统上进行高级程序设计,涵盖了从系统调用、...

    UNIX环境高级编程(清晰PDF中文第一版)

    《UNIX环境高级编程》是一本深受IT专业人士喜爱的经典著作,尤其对于那些致力于深入理解Linux操作系统以及UNIX系统的开发者和系统管理员而言,这本书具有极高的参考价值。作为“学习Linux最好的两本书之一”,它与...

    UNIX环境高级编程(PDF)

    本书的前15章着重于理论知识的阐述,主要内容包括UNIX文件和目录、进程环境、进程控制、 进程间通信以及各种I/O。在此基础上,分别按章介绍了多个应用实例,包括如何创建数据库函数库, PostScript 打印机驱动程序,...

    UNIX环境高级编程-009_进程关系

    《UNIX环境高级编程》第9章主要讨论的是进程间的关系,包括进程的父子关系、进程组、对话期的概念,以及登录shell和相关进程之间的交互。这一章的内容是建立在前一章关于进程控制的基础之上的,进一步深入探讨了进程...

    UNIX环境高级编程+UNIX网络编程卷1.PDF版

    《UNIX环境高级编程》是学习UNIX系统编程的权威指南,涵盖了系统调用、进程管理、文件I/O、内存管理和错误处理等多个方面。 1. **系统调用**:UNIX系统的核心在于其内核提供的系统调用,它们是程序与操作系统交互的...

Global site tag (gtag.js) - Google Analytics