Linux c 进程的理解

Linux进程的理解:

1.       父子进程的关系

         独立的两个进程

         互为父子关系

2.       问题:

2.1. 父进程先结束?

                       子进程就依托根进程init:孤儿进程

                        孤儿进程没有任何问题(没有任何危害)

2.2. 子进程先结束?

                        子进程会成为僵尸进程。

                         僵尸进程不占用内存、cpu.但在进程任务树上的节点

                        僵尸进程会造成一个进程名额的浪费,所要处理僵尸进程

3.       僵尸进程使用wait回收

        wait函数:pid_t wait(int * status);

进程一旦调用了wait,就立即阻塞自己,由wait自动分析是否当前进程的某个子进程已经退出,如果让它找到了这样一个已经变成僵尸的子进程,wait就会收集这个子进程的信息,并把它彻底销毁后返回;如果没有找到这样一个子进程,wait就会一直阻塞在这里,直到有一个出现为止。
参数status用来保存被收集进程退出时的一些状态,它是一个指向int类型的指针。但如果我们对这个子进程是如何死掉的毫不在意,只想把这个僵尸进程消灭掉,(事实上绝大多数情况下,我们都会这样想),我们就可以设定这个参数为NULL。

  

僵尸进程回收例子:

 

#include<stdio.h>

#include<unistd.h>

#include<sys/wait.h>

 

int main()

{

      if(fork()==0)

      {

              printf(“子进程:%d\n”,getpid());

             sleep(5);

              printf(“子进程退出\n”);

              return 88;

      }

      else

      {

              printf(“父进程:%d\n”,getpid());

              int status;

              int pid=wait(&status);

              printf(“父进程收回子进程%d,子进程返回码:%d”,pid,WEXITSTATUS(status));

              sleep(20);

              return 0;

      }

}

 

    

 

4.       父进程怎么知道子进程退出?

        子进程结束通常会向父进程发送一个信号:SIGCHLD

5. 父进程处理子进程退出信号

                               signal(intsig,void(*fun)(int));

                               向系统注册:只要sig信号发生,系统停止进程,并调用函数fun

                               当函数执行完毕,继续原来进程

                               5.1.实现处理函数

                               5.2.使用signal邦定信号与函数

僵尸进程回收例子:

 

 

#include<stdio.h>

#include<unistd.h>

#include<sys/wait.h>

#include<signal.h>

 

void deal(int s)

{

    int status;

    int pid=wait(&status);

    printf(“父进程收回子进程%d,子进程返回码:%d”,pid,WEXITSTATUS(status));

}

 

int main()

{

      if(fork()==0)

      {

              printf(“子进程:%d\n”,getpid());

              sleep(5);

              printf(“子进程退出\n”);

              return 88;

      }

      else

      {

              printf(“父进程:%d\n”,getpid());

              signal(SIGCHLD,deal);

              while(1)

              {

                      sleep(1);

               }

              return 0;

      }

}

 

注:sleep函数,当有信号传过来时,sleep不会堵塞,会跳到sleep函数的下一条语句执行。

 

    6. 父子进程的资源访问

                                   6.1.内存资源

                                   6.2.文件资源

 

例子:

 

#include<stdio.h>

#include<unistd.h>

 

void main()

{

     inta=20;

     if(fork())

    {

          printf(“父进程:%d\n”,a);

     

    }

    else

    {

         printf(“子进程:%d\n”,a);

    }

}

 

运行结构:

子进程:20

父进程:20

 

例子说明:子进程克隆了父进程的整个内存区域

 

列子2:

 

#include<stdio.h>

#include<unistd.h>

 

void main()

{

     inta=20;

     if(fork())

    {

          printf(“父进程:%d\n”,a);

          a=99;

     

    }

    else

    {

         printf(“子进程:%d\n”,a);

         sleep(3);

         printf(“子进程:%d\n”,a);

         

         

    }

}

 

运行结果:

子进程:20

父进程:20

子进程:20

 

列子说明:但内存区域指向不同的物理空间尽管克隆,但内存独立. 不能相互访问

 

 

例子3:

 

#include<stdio.h>

#include<unistd.h>

#include<sys/mman.h>

 

void main()

{

     int*a=mmap(0,4,PROT_READ|PROT_WRITE,MAP_ANONYMOUS|MAP_SHARED,0,0);

     if(fork())

    {

           *a=20;

          printf(“父进程:%d\n”,a);

          *a=99;

     

    }

    else

    {

         printf(“子进程:%d\n”,a);

         sleep(3);

         printf(“子进程:%d\n”,a);

         

         

    }

}

 

运行结果:

子进程:20

父进程:20

子进程:99

 

但,当把MAP_SHARED改成MAP_PRIVATE时:

运行结果:

子进程:20

父进程:20

子进程:20

 

例子说明:

 

映射内存:

              MAP_SHARED:映射到同一物理内存

              MAP_PRIVATE:映射到不同的物理内存.

实现父子进程的数据交换可以使用内存映射的方式

使用sbrk方式是可以映射到同一块物理内存的

 

 

例子3:

#include<stdio.h>

#include<unistd.h>

#include<fcntl.h>

 

void main()

{

     int fd=open(“text.txt”,O_RDWR);

     if(fork())

     {

          char buf[1024]={0};

          lseek(fd,0,SEEK_SET);

          read(fd,buf,1024);

          printf(“父进程:%s”,buf);

          close(fd);

     }

     else

     {

          char buf[1024]={0};

          read(fd,buf,1024);

          printf(“父进程:%s”,buf);

          close(fd);

 

     }

}

 

运行结构:子进程和父进程都能读取到文件的内容,父进程中用lseek是因为程序先执行子进程,子进程读取完后位置指针指向文件的末尾,影响了父进程,父进程不能读取到内容。

                                  

列子说明:两个进程之间,文件描述符号指向的是同一个文件内核对象.

注:文件描述符要关闭两次,子进程克隆的文件描述符也得关闭

 

 

 

 

 

 

你可能感兴趣的:(c,linux,进程,进程数据共享)