一.启动一个新进程
1.#include<stdio.h>
int system (const char *string);
运行以字符串参数的形式传递给它的命令并等待该命令的执行(会阻塞在这)
等同于$sh -c string
命令后加&,后台运行
2.替换进程映像
exec由一系列的函数组成,可以把当前进程替换为一个新进程,新进程由path或file参数指定。
分为两大类execl,execlp和execle是参数个数可变的。另一类是execv 和 execv p,其第二个参数是一个字符串数组。启动时会把这些参数传递给main函数。
这些函数都是由execve实现的。
#include<unistd.h>
char **environ;
int execl(const char *path,const char *arg0,..., (char*)0);
int execlp(const char *file,const char *arg0,..., (char*)0);
int execlp(const char *path,const char *arg0,..., (char*)0,char *envp[]);
int execv(const char *path,const char *arg0,..., (char*)0);
int execlp(const char *file,const char *arg0,..., (char*)0);
int execlp(const char *path,const char *arg0,..., (char*)0,char *envp[]);
以字母P结尾的函数使用系统的PATH环境变量来搜索新程序的可执行文件的路径,如果不在PATH中,file就要使用包含目录在内的绝对路径了
全局变量environ可以把一个值传递到新的程序中,,execle和execvp可以通过参数envp传递字符串数组作为新的环境变量
示例程序
#include <unistd.h> char * const ps_argv[] = {"ps',"ax",0}; //example environment,not terribly useful char * const ps_envp[] = {"PATH = /bin:/usr/bin","TERM = console",0}; execl("/bin/ps","ps","ax",0); execlp("ps","ps","ax",0); execle("/bin/ps","ps","ax",0,ps_envp);/*pass own environment*/ execv("/bin/ps",ps_argv); execvp("ps',ps_argv); execve("/bin/ps",ps_argv,ps_envp);
2.复制进程映像
通过调用fork来复制一个进程,在进程表中创建一个新的表项,执行的的代码和当前进程一样,但新进程有自己的数据空间,环境和文件描述符。fork和exec在一块可以完成创建一个新进程所需要的一切。
#include<unistd.h> #include<sys/types.h> pid_t fork(void);
fork失败返回-1,在子进程中返回0,fork函数示例
pid_t new_pid; new_pid = fork(); switch(new_pid){ case -1://error break; case 0://这是子进程 break; default://这里是父进程 break; }
fork函数使用写时拷贝(copy-on-write)页实现,写时拷贝是一种延迟甚至可以免除数据拷贝的技术。调用过fork函数后,内核此时并不复制种鸽内核地址空间,而是让父进程和子进程共享一个拷贝。只有在数据需要被写入的时候,数据才会被复制,从而使进程拥有自己的拷贝。资源的复制只有在需要写入的时候才进行,在这之前,只是以只读的方式共享,fork之后立即调用exec,fork的开销就只有复制父进程的页表和给子进程创建唯一的进程描述符。
3.等待一个进程;
#include<sys/wait.h>
pid_t wait(int *stat_loc);返回等待进程的pid,如果stat_loc非空,状态信息会写入其指向的位置,状态信息为main函数的返回值或者exit函数的退出码。sys/wait.h文件中定义的宏来解释状态信息。
4.僵尸进程:(这个待补充)