Linux c 进程的理解

本文深入探讨了 Linux 下的进程管理,包括父子进程的关系、僵尸进程的产生及处理方式,以及如何通过信号机制和 wait 函数来管理子进程的状态。此外,还介绍了父子进程间资源访问的具体情况。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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>

intmain()

{

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));

}

intmain()

{

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>

voidmain()

{

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是因为程序先执行子进程,子进程读取完后位置指针指向文件的末尾,影响了父进程,父进程不能读取到内容。

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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值