GNU/Linux 进程模型
GNU/Linux进程有两种基本类型,内核线程和用户进程。内核线程是在内核中由kernel_thread()函数创建,用户进程由fork()和 clone()创建。(讨论用户进程)
创建一个子进程(由fork创建),就创建了一个新的子任务,并为它复制了父任务使用的内存。两个进程使用的内存是相互独立的。在调用fork的时候,父进程当时的所有变量对子进程都是可见的;但在fork执行完成之后,父进程的变量的任何变动对子进程都是不可见的。
在创建一个新任务的时候,父进程使用的内存并不是真正的复制给子任务,他们都指向同一处内存空间,但把内存页面标记为copy-on-write。当任何一个进程试图向这些内存中写入内容时,就会产生一组新的内存页面由这个进程私有。默认情况下,子进程继承文件描述符、内容映像以及CPU状态。
GNU/Linux中每一个进程都有一个唯一的描述符,称为进程ID(或进程号id),每一个进程都有一个父进程(init进程除外)。
函数getpid()获得当前的进程号;函数getppid()获得当前进程的父进程的进程号,函数getuid()获得用户id,函数getgid()获得组id
用fork创建一个子进程
当API函数fork返回时,已经分裂出了新的进程,但fork的返回值指明的是进程运行的上下文环境。
Pid_t pid;
….
Pid = fork();
If (pid > 0)
{
//父进程的上下文,子进程号为pid
}
Else if (pid == 0)
{
//子进程上下文
}
Else
{
//父进程上下文,但fork调用出错,没有创建子进程
}
对于父子进程中共有的变量,如果对该变量发生写操作,则会将内存划分开,每个进程拥有各自的内存,这些内存相互独立。即每个进程都为自己复制一份独有的变量集。
创建者进程同步
在父进程上下文环境中调用了wait函数,函数wait把父进程挂起,直到子进程退出。如果父进程没有调用wait函数等待子进程退出,子进程就会成为“僵尸进程”(即既不是活的,也不是死的)。允许僵尸进程存在会导致问题,因为他们浪费了资源。因此需要正确处