进程标识符
每个进程都有一个非负整数表示为宜进程ID。但进程ID也可以重用,当一个进程终止后,其进程ID就可以再次被使用了。
进程ID是0的进程通常是调度进程,常常被称为交换进程,是内核的一部分,进程ID是1的进程为init进程,在自举过程结束时有内和调用。init进程绝不会终止,他是一个普通的用户进程,但是以超级用户特权运行。进程ID2是页守护进程,此进程负责支持虚拟存储系统的分页操作。
#include<unistd.h>'
pid_t getpid(void); //调用进程的进程ID
pid_t getppid(void) ; //调用进程的父进程ID
uid_t getuid(void); //调用进程的实际用户ID
uid_t geteuid(void); //调用进程的有效用户ID
gid_t getgid(void); //调用进程的实际组ID
gid_t getegid(void); //调用进程的有效组ID
fork()函数
#include<unistd.h>
pid_t fork(void); //子进程中返回0,父进程中返回进程ID
子进程和父进程继续执行fork调用后的指令。子进程是父进程的副本。子进程获得父进程的数据空间、堆、栈的副本。父子进程共享正文段。
一般来说,fork之后是父进程限制性还是子进程先执行时不确定的。这取决于内核所使用调度算法。如果要求父子进程之间相互同步,则要求某种形式的进程间通信。
fork的一个特性是父进程所有打开的文件描述符被复制到子进程中。父子进程的每个相同的打开的文件描述符共享一个文件表项。这种共享文件的方式,使得父子进程对同一文件使用了一个文件偏移量。
在重定向父进程的标准输出时,子进程的标准输出也被重定向了。
fork之后处理文件描述符有两种情况:
1)父进程等待子进程完成。
2)父子进程各自执行不同的程序段。这种情况下,fork之后,父子进程各自关闭他们不需要的文件描述符,这样就不会干扰对方使用的文件描述符。
除了打开文件外,父进程的属性很多子进程也会继承
1)实际用户ID,实际组ID,有效用户ID,有效组ID。
2)附加组
3)进程组ID
4)回话ID
5) 控制终端
6)设置用户ID标志和设置组ID标志
7) 当前工作目录
8)根目录
9)文件模式创建屏蔽字
10)信号屏蔽的安排
11)针对任意打开文件描述符在执行时关闭标志
12)环境
13)链接的共享存储段
14)存储映射
15)资源限制
父子进程的区别
1)进程ID不同
2)fork返回值不同
3)两个进程具有不同的父进程ID,
4)子进程的tms_utime, tms_stime, tms_cutime以及tms_ustime均被设置为0
5)父进程的文件锁不会被子进程继承
6)子进程的未处理的闹钟被清除
7)子进程的未处理信号集被设置为NULL
使得fork失败的原因:系统中有太多的进程,或者该用户ID的进程数超过了系统限制
fork有两种用法
1)一个父进程希望负值自己,使父子进程同时执行不同的代码段。
2)一个进程执行一个不同的程序
vfork函数
vfork用于创建一个进程,此进程的目的是exec一个新程序。其与fork一样都创建一个子进程,但是他并不将父进程的地址空间完全付之于子进程中,因为子进程会立即调用exec。相反子进程在调用exec或exit之前,她在父进程的地址空间中运行
exit函数
进程有5中终止方式
1)在main函数内执行return语句
2)调用exit函数,其操作包括调用各终止处理程序,然后关闭所有标准I/O流
3)调用_exit()或_Exit()函数。其目的是位进程提供一种无需运行惩治处理程序或者信号处理程序而终止的方法。对标志I/O是否冲刷,取决于实现。在Unix中,并不冲刷
4)进程的最后一个线程在其启动历程中执行返回语句。但是该现成的返回值不会用作进程的返回值。
5)进程最后一个线程调用pthead_exit函数
三种异常终止的方法
1)调用abort,产生SIGABRT信号
2)当进程接收到某些信号时。
3)最后一个线程对取消请求作出响应。按系统默认,取消以延迟方式发生。
不管进程以何种方式终止,最后都会执行内核中的一段代码,这段代码关闭所有打开的文件描述符。
对于父进程已经终止的进程,他们的父进程都将改变为init进程。大致过程为:在一个进程终止时,内核会逐个检查所有活动的进程,以判断他们是否是要终止的进程的子进程,如果是则将其进程的父进程ID改为1
内核位每个终止子进程保存了一定量的信息,所有当中只进程的父进程调用wait或waitpid时,可以获得这些信息。这些信息至少包括了进程的终止状态,该进程的ID,该进程使用CPU时间的总量。内核会释放进程所使用的所有的存储区,所有打开的文件。如果父进程尚未对其进行善后处理,这样的进程成为僵死进程。
wait和waitpid函数
当一个进程正常或者异常结束时,内核就像其父进程发送SIGCHLD信号。因为子进程终止是个异步事件,所以这种信号也是内核项父进程发的异步通知。这种信号系统的默认动作时忽略它。
调用wait或waitpid的进程可能发生如下情况
1)如果其所有的子进程还在运行,则阻塞
2)如果一个子进程终止,则等待父进程获得其终止状态,则取得子进程终止状态立即返回
3)如果他没有子进程,则立即出错返回
#include<sys/wait.h>
pid_t wait()