OS | Process

linux多进程

1. fork()创建进程,创建一份父进程的拷贝;在父进程中返回的是子进程id,在子进程中返回的是0;失败时返回-1;

2. fork()经常和exec()结合,exec() 覆盖了原进程的空间,转而执行其他程序;

3. 杀掉父进程,不会同时杀掉子进程;

孤儿进程:一个父进程退出,而它的一个或多个子进程还在运行,那么那些子进程将成为孤儿进程。孤儿进程将被init进程(进程号为1)所收养,并由init进程对它们完成状态收集工作。

僵尸进程:一个进程使用fork创建子进程,如果子进程退出,而父进程并没有调用wait或waitpid获取子进程的状态信息,那么子进程的进程描述符仍然保存在系统中。这个子进程称之为僵尸进程。系统所能使用的进程号是有限的,如果大量的产生僵死进程,将因为没有可用的进程号而导致系统不能产生新的进程。孤儿进程并不会有什么危害。

当我们寻求如何消灭系统中大量的僵死进程时,答案就是把产生大 量僵死进程的那个元凶枪毙掉(也就是通过kill发送SIGTERM或者SIGKILL信号啦)。枪毙了元凶进程之后,它产生的僵死进程就变成了孤儿进程,这些孤儿进程会被init进程接管,init进程会wait()这些孤儿进程,释放它们占用的系统进程表中的资源,这样,这些已经僵死的孤儿进程 就能瞑目而去了。

避免zombie的方法:

  • 忽略信号SIGCHLD, signal(SIGCHLD,SIG_IGN); 
  • 父进程中调用wait或waitpid;
  • 调用两次fork();父进程一次fork()后产生一个子进程随后立即执行waitpid(子进程pid, NULL, 0)来等待子进程结束,然后子进程fork()后产生孙子进程随后立即exit(0)。这样子进程顺利终止(父进程仅仅给子进程收尸,并不需要子进程的返回值),然后父进程继续执行。这时的孙子进程由于失去了它的父进程(即是父进程的子进程),将被转交给Init进程托管。于是父进程与孙子进程无继承关系了,它们的父进程均为Init,Init进程在其子进程结束时会自动收尸,这样也就不会产生僵尸进程了。ddkkk
 1 #include <stdio.h>  

 2 #include <stdlib.h>  

 3 #include <sys/wait.h>  

 4 #include <sys/types.h>  

 5 #include <unistd.h>  

 6 

 7 int main() {     

 8     pid_t pid;     

 9 

10     if ((pid = fork()) < 0) {     

11         fprintf(stderr,"Fork error!\n");     

12         exit(-1);     

13     } else if (pid == 0) { // child 

14         if ((pid = fork()) < 0) {      

15             fprintf(stderr,"Fork error!\n");     

16             exit(-1);     

17         } else if (pid > 0) {    

18             printf("child: %d, parent pid = %d\n", getpid(), getppid());     

19             exit(0); // child exit   

20         } else {

21             printf("grandchild: %d, parent pid = %d\n", getpid(), getppid());     

22             exit(0);

23         }

24     } else {

25         printf("pid: %d\n", getpid());

26         if (waitpid(pid, NULL, 0) != pid) {     

27             fprintf(stderr,"Waitpid error!\n");     

28             exit(-1);     

29         }     

30         return 0; 

31     }

32 }     

输出为:

1 root@xxj-VirtualBox:~/interview# ./process 

2 pid: 7411

3 child: 7412, parent pid = 7411

4 root@xxj-VirtualBox:~/interview# grandchild: 7413, parent pid = 1755

5 

6 root@xxj-VirtualBox:~/interview# ps ax|grep 1755

7  1755 ?        Ss     0:00 init --user

8  7415 pts/3    S+     0:00 grep --color=auto 1755

父进程是7411,子进程的父进程是7411没错,孙进程是7413,现在它被init进程(1755)回收了。

打印父进程的父进程发现是5976,5976是bash的pid。

4. wait() 等待子进程;可以获取子进程的返回状态;

5. system()就是用fork()+exec()+wait()实现;

6. execlp(),每一个是可执行文件的路径,第二个参数开始就是arg0,arg1,...,所以arg0必须就是可执行文件名,最后一个arg必须是NULL; 

 1 int main() {

 2     int pid = fork();

 3     if (pid < 0) {

 4         fprintf(stderr, "fork failed");

 5         return -1;

 6     } else if (pid == 0) {

 7         cout << "child process" << endl;

 8         execlp("/bin/touch", "touch", "/root/lab/os/1", NULL);    

 9     } else {

10         cout << "pid of child:" << pid << endl;

11         int status;

12         wait(&status);

13         cout << "status of child:" << status << endl;

14     }

15     return 0;

16 }

 共享内存通信

1. shm_open打开或者创建共享内存object,名字必须以/开头;一开始大小为0;需要通过ftruncate()设置大小;

2. 用mmap将shared memory object映射到内存;映射为MAP_SHARED,这样在其他进程中可见;即使进程退出了,在没有调用shm_unlink之前,其他进程还是可以访问这一块区域的。

 1 #include <sys/mman.h>

 2 #include <sys/stat.h>        

 3 #include <fcntl.h>          

 4 #include <stdio.h>

 5 #include <unistd.h>

 6 #include <sys/types.h>

 7 

 8 int main() {

 9     int shmID = shm_open("/test", O_CREAT | O_RDWR, 0666);

10     if (shmID < 0) {

11         fprintf(stderr, "shm create failed\n");

12         return -1;

13     }

14     ftruncate(shmID, 2014);

15     char* p = (char*)mmap(NULL, 2014, PROT_WRITE, MAP_SHARED, shmID, 0);

16     for (int i = 0; i < 2000; i++) {

17         p[i] = '0' + i % 10;

18     }

19     munmap(p, 2014);

20     return 0;

21 }
 1 #include <stdio.h>

 2 #include <sys/mman.h>

 3 #include <sys/stat.h>       

 4 #include <fcntl.h>         

 5 

 6 int main() {

 7     int shmID = shm_open("/test", O_RDONLY, 0666);

 8     if (shmID < 0) {

 9         fprintf(stderr, "shm open fail\n");

10         return -1;

11     }

12     char* p = (char*)mmap(NULL, 2014, PROT_READ, MAP_SHARED, shmID, 0);

13     if (p == NULL) {

14         return -1;

15     }

16     for (int i = 0; i < 100; i++) {

17         printf("%c ", p[i]);

18     }

19     printf("\n");

20 

21     shm_unlink("/test");

22     munmap(p, 2014);

23     return 0;

24 }

 

你可能感兴趣的:(process)