进程的创建
4 int main(void){
5 pid_t pid;
6
7 printf("before :pid is %d\n",getpid());
8 if((pid=fork())==-1){
9 perror("fork()");
5 pid_t pid;
5 pid_t pid;
6
7 printf("before :pid is %d\n",getpid());
8 if((pid=fork())==-1){
9 perror("fork()");
10 exit(1);
11 }
12 printf("after:pid is %d\n",getpid());
13 sleep(1);
14 return 0;
**运行结果**
$ ./a.out
before :pid is 25710 //进程id
after:pid is 25710 //父进程id
after:pid is 25711 //子进程id
- 父进程和子进程除了代码是共享的之外,其他的都是原件与副本的关系。既然是副本,就说明两个是不同的进程,有各自的虚拟内存,最后通过mmu映射到物理内存当中去。
- 由fork又引出了vfork这一概念,vfork和fork的作用是相同的,但是不同的是它的子进程和父进程共享地址空间,。而且vfork可以保证子进程先运行。
进程的终止
- 进程退出有三种情况:运行并且结果正确;运行结果不正确;异常退出
- 正常退出:从main函数返回,调用exit,_exit函数
- 异常退出:Ctrl+c,信号终止
- exit和_exit的区别:exit在退出之前会关闭所有的流,所有的缓存数据也都被写入
,完成之后才退出;_exit是直接退出。
进程的等待
- 父进程提前退出,而子进程想要报告信息给父进程找不到对象,就会进入僵尸进程,造成内存泄漏
- 进程一旦进入了僵尸状态,就无法杀死了
- 而父进程派给子进程的任务完成的如何,也是需要返回的
- 所以就引出了进程等待,可以回收子进程资源,获取子进程退出信息
以下是一个进程等待的代码
1 #include<stdio.h>
2 #include<unistd.h>
3 #include<stdlib.h>
4 #include<errno.h>
5 #include<sys/types.h>
6
7 int main(void){
8 pid_t pid;
9
10
11 pid=fork();
12 if(pid==-1){
13 perror("fork()");
14 exit(1);
15 }
16
17
18 if(pid==0){
19 sleep(10);
20 exit(10);
21 }
22 else{
23
24
25 int st;
26 int ret=wait(&st);
27
28
29 if(ret>0&&(st&0X7F)==0){
30 printf("child exit code:%d",(st>>8)&0XFF);
31 }
32
33 else if(ret<0){
34 printf("sig code:%d\n",st&0X7F);
35 }
36 }
**运行结果**
./a.out
child exit code:10
pid_t waitpid(pid_t pid, int *status, int options);
进程程序的替换
- 用fork创建了子进程,子进程和父进程执行的是相同的代码,但是子进程往往要调用exec函数来执行自己的程序,exec函数不创建新的进程,所以进程id不会变。
- 最终的调用都会到execve 这个函数上
- v代表了数组,可以概括list
- e代表了自己组装环境变量,不可以使用环境变量path,所以需要写全路径。
简易的xshell
1 #include<unistd.h>
2 #include<stdio.h>
3 #include<stdlib.h>
4 #include<sys/wait.h>
5 #include<string.h>
6 char *argv[8]
7 int argc=0;
8
9
10
11 void parse(char *buf)
12 {
13 int i;
14 int status=0;
15
16 for(i=0;buf[i];i++){
17 if(!isspace(buf[i])&&status==0)
18 {
19 argv[i++]=buf+i;
20 status=1;
21 }
22 else if(isspace(buf[i]))
23 {
24 status=0;
25 buf[i]=0;
26 }
27 }
28 argv[i]=NULL;
29 }
31
32 void execute(void)
33 {
34 pid_t pid;
35
36 switch(pid){
37 case -1:
38 perror("fork");
39 exit(EXIT_FAILURE);
40 break;
41 case 0:
42 execvp(argv[0],argv);
43 perror("execvp");
44 exit(EXIT_FAILURE);
45 default:
46 {
47 int st;
48 while(wait(&st)!=pid)
49 ;
50 }
51 }