相关函数列表
//下列函数返回一个进程的标识符 #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 | 新格式记录 |
参考
相关推荐
《UNIX环境高级编程》详细解释了信号的概念、发送、接收和处理,以及信号在进程控制中的应用,帮助读者理解如何优雅地处理程序中断和异常情况。 此外,书中还涉及了进程环境、系统调用接口、编译和链接、动态装载、...
《UNIX环境高级编程》是一本深入探讨UNIX系统编程的权威参考书籍。它涵盖了UNIX编程的各个方面,从基础的UNIX系统结构和原理,到文件操作、进程控制、进程间通信、多线程编程、网络编程以及终端I/O和伪终端等内容。...
### UNIX环境高级编程知识点概述 #### 一、UNIX基础知识 **1.1 引言** 在计算机科学领域,操作系统作为连接硬件与软件的桥梁,为应用程序提供了必要的服务,包括但不限于执行新程序、打开文件、读取文件内容、...
《UNIX环境高级编程(第3版)》在保持前一版风格的基础上,根据最新的标准对内容进行了修订和增补,反映了最新的技术发展。书中除了介绍UNIX文件和目录、标准I/O库、系统数据文件和信息、进程环境、进程控制、进程关系...
《Unix环境高级编程》是一本深受程序员和系统管理员喜爱的经典之作,主要涵盖了在Unix操作系统环境下进行高级编程的各种技术和方法。这本书分为多个章节,详细讲解了Unix系统接口、进程管理、文件系统、网络通信等...
《UNIX环境高级编程》是一本深受程序员和系统管理员喜爱的经典之作,主要涵盖了在UNIX操作系统上进行高级编程的各种技术和实践。这本书以清晰的结构和深入的解释,为读者提供了丰富的UNIX编程知识,帮助他们掌握在这...
《Unix环境高级编程》是一本深入探讨Unix操作系统编程的经典之作,由W. Richard Stevens撰写,是许多计算机科学专业学生和专业开发者的必备参考书。这本书详细介绍了如何在Unix系统上进行系统级编程,包括文件I/O、...
"UNIX环境高级编程"通常涵盖的主题包括进程管理、文件I/O、信号处理、网络编程、系统调用接口以及内存管理等。 课后习题往往旨在巩固和深化对这些概念的理解。以下是一些可能涉及的知识点: 1. **进程管理**:包括...
《UNIX环境高级编程》是一本深受程序员和系统管理员喜爱的经典之作,它由W. Richard Stevens撰写,对中国乃至全球的UNIX和Linux开发者具有深远影响。这本书深入浅出地讲解了在UNIX系统上进行程序开发的各种技术和...
### Unix环境高级编程 第三版 知识点详解 #### 一、书籍概述与目标读者 《Unix环境高级编程》第三版是一本针对高级程序员和网络专业人士编写的实用参考书。该系列书籍由Addison-Wesley出版社创建于1990年,旨在为...
### Unix环境高级编程知识点概述 #### 一、Unix基础知识概览 **1.1 引言** 本书聚焦于探讨Unix操作系统及其多种版本为程序提供的各项服务。这些服务包括但不限于执行新程序、文件操作(如打开、读取)、内存分配...
《Unix环境高级编程》与《Unix网络编程:进程间通信》是两本在计算机科学领域具有深远影响力的经典著作。它们涵盖了Unix系统的核心概念和技术,对于理解操作系统原理、进行系统级编程以及深入研究网络通信有着不可...
《UNIX环境高级编程》是Unix系统编程领域的一本经典之作,被誉为“圣书”,对于学习Linux开发技术的人员来说,是一本不可或缺的参考书。这本书深入讲解了在Unix环境下进行系统级编程的各种技术和细节,涵盖了从基本...
《UNIX环境高级编程》(第三版) 是一本深入讲解UNIX操作系统编程的经典著作,它由W. Richard Stevens撰写,是IT行业内广泛使用的参考资料。这本书详细介绍了如何在UNIX系统上进行高级程序设计,涵盖了从系统调用、...
《UNIX环境高级编程》是一本深受IT专业人士喜爱的经典著作,尤其对于那些致力于深入理解Linux操作系统以及UNIX系统的开发者和系统管理员而言,这本书具有极高的参考价值。作为“学习Linux最好的两本书之一”,它与...
本书的前15章着重于理论知识的阐述,主要内容包括UNIX文件和目录、进程环境、进程控制、 进程间通信以及各种I/O。在此基础上,分别按章介绍了多个应用实例,包括如何创建数据库函数库, PostScript 打印机驱动程序,...
《UNIX环境高级编程》第9章主要讨论的是进程间的关系,包括进程的父子关系、进程组、对话期的概念,以及登录shell和相关进程之间的交互。这一章的内容是建立在前一章关于进程控制的基础之上的,进一步深入探讨了进程...
《UNIX环境高级编程》是学习UNIX系统编程的权威指南,涵盖了系统调用、进程管理、文件I/O、内存管理和错误处理等多个方面。 1. **系统调用**:UNIX系统的核心在于其内核提供的系统调用,它们是程序与操作系统交互的...