在linux系统中,对于进程进行控制的主要系统调用以下所示
- fork:用于创建一个新进程。
- exit:用于终止进程
- exec:用于执行一个应用程序
- wait:将父进程挂起,等待子进程终止
- getpid:获取当前进程的进程ID
- nice:改变进程的优先级
1.fork函数
函数声明
#include<sys/types.h>
#include<unistd.h>
pid_t fork(void);
根据书上所介绍的,fork函数有两个返回值,调用一次返回两次,一个是父进程调用fork后的返回值,一个是子进程中fork函数的返回值,该返回值为0。fork函数返回两次的前提是进程创建成功,如果进程创建失败,则只返回-1
以下是man手册里的部分相关描述:
fork() creates a new process by duplicating the calling process. The new
process is referred to as the child process. The calling process is
referred to as the parent process.
The child process and the parent process run in separate memory spaces.
At the time of fork() both memory spaces have the same content. Memory
writes, file mappings (mmap(2)), and unmappings (munmap(2)) performed by
one of the processes do not affect the other.
以下这段话是从别人的博客中看到的,我觉得很不错,较为详细地剖析了两次返回的实质
对于fork来说,父子进程共享同一段代码空间,所以给人的感觉好像是有两次返回,其实对于调用fork
的父进程来说,如果fork出来的子进程没 有得到 调度,那么父进程从fork系统调用返回,同时分析sys_fork知道
,fork返回的是子进程的id。再看fork出来的子进程,由 copy_process函数可以看出,子进程的返回地址为ret_from_fork(和父进程在同一个代码点上返回),返回值直接置为0。所以当子进 程得到调度的时候,
也从fork返回,返回值为0。关键注意两点:1.fork返回后,父进程或子进程的执行位置。(首先会将当
前进程eax的值做为返回值)2.两次返回的pid存放的位置。(eax中)
进程调用copy_process得到lastpid的值(放入eax中,fork正常返回后,父进程中返回的就是lastpid)
子进程任务状态段tss的eax被设置成0,fork.c 中p->tss.eax=0;(如果子进程要执行就需要进程切换,
当发生切换时,子进程tss中的eax值就调入eax寄存器,子进程执行时首先会将eax的内容做为返回值)
当子进程开始执行时,copy_process返回eax的值。
fork()后,就是两个任务同时进行,父进程用他的tss,子进程用自己的tss,在切换时,各用各的eax中的值.
所以,“一次调用两次返回”是2个不同的进程!
2.exec函数族
#include<unistd.h>
int execl(const char *path, const char *arg, ...)
int execv(const char *path, char *const argv[])
int execle(const char *path, const char *arg, ..., char *const envp[])
int execve(const char *path, char *const argv[], char *const envp[])
int execlp(const char *file, const char *arg, ...)
int execvp(const char *file, char *const argv[])
使用fork或vfork函数创建子进程后,子进程通常会调用exec函数来执行另外一个程序。系统调用exec用于执行一个可执行程序以代替当前进程的执行映像
注意:exec调用并没有生成新进程。一个进程一旦调用exec函数。它本身就“死亡了”,系统把代码段替换成新的程序的代码,废弃原有的数据段和堆栈段。并为新程序分配新的数据段与堆栈段,唯一保留的就是进程ID,也就是说,对系统而言,还是同一个进程,不过执行的已经是另外一个程序了。
具体的函数说明见man exec中对整个exec族函数的详细解释。
3.wait/waitpid函数
函数原型
#include<sys/types.h>
#include<sys/wait.h>
pid_t wait(int *statloc);
pid_t waitpid(pid_t pid,int *statloc,int options);
如果子进程先于父进程退出时,如果父进程没有调用wait和waitpid函数,子进程就会进入僵死状态。如果父进程调用了wait或waitpid函数,就不会使子进程变成僵尸进程。
wait函数使父进程暂停执行,直到它的第一个子进程结束为止。该函数的返回值是终止运行的子进程PID。参数statloc所指向的变量存放子进程的退出码。即从子进程的main函数返回的值或子进程中exit函数的参数。
4.gitpid函数
#include<sys/types.h>
#inlcude<unsitd.h>
pid_t getpid(void);
系统调用getpid获取当前进程的ID。
man手册中的部分描述
getpid() returns the process ID (PID) of the calling process. (This is often used by rou‐
tines that generate unique temporary filenames.)