linux:09写时拷贝&父子进程文件共享&信号使用

1.写时拷贝

注:32.64位:ALU的宽度,cpu的处理能力(一次处理数据的宽度)

1.malloc函数仅仅是开辟虚拟空间名,真正开辟物理空间是在程序使用开辟地空间时。

2.fork之后,子进程会拷贝父进程的pcb结构,然后会对pcb里面的数据修改。父进程的页表直接拷贝给子进程。父子进程共享所有的存储空间。(没有修改页表的内容)

3.写时拷贝技术:fork之后并不会复制空间,而是任意一个进程试图修改数据后,才会将试图修改的数据所在的那页复制出来

流程图:
在这里插入图片描述
代码:

int main()
{
char *ptr = (char *)malloc(1024*1024*1024);
assert(ptr != NULL);

int i=0;
for(;i<32;++i)
{
memset(ptr+i*1024*1024*32,'a',1024*1024*32);
sleep(1);
}

pid_t n = fork();
assert(n != -1);

if(n==0)
{
printf("child start\n");
int i = 0;
for(;i<32;++i)
{
memset(ptr+i*1024*1024*32,'b',1024*1024*32);
}
else
{
sleep(100);
}

free(ptr);
}

2.swap:交换分区

1.解释:对于内存的补充,空间在磁盘中。
详细内容:
https://coolnull.com/3699.html

3.文件描述符

1.fork之前打开的文件描述符
2.父子进程共享fork之前打开文件的读写偏移量
代码:

int main()
{
int fd = open("a.txt",O_RDWR);
assert(fd != -1);

pid_t n = fork()//创建子进程
assert(n != -1);

if(n == 0)
{
char buff[128] = {0};
read (fd,buff,5);
printf("child: %s\n",buff);
}
else
{
sleep(1);//先让子进程执行,父进程休眠一秒
char buff[128] = {0};
read(fd,buff,5);
printf("father: %s\n",buff);
}

close(fd);
exit(0);
}

4.僵死进程

1.含义:PCB存在,进程主体释放
2.处理方法:信号
3.出现的原因:子进程结束,父进程未获取子进程的退出码,从而子进程不得不保存退出码,所以整个PCB也就无法释放。
4.父进程获取退出码:
pid_t wait(int *reval);
pid_t waitpid();
5.阻塞与非阻塞:
阻塞运行:所需条件未准备好,函数不会返回,直到条件满足。从而造成进程执行阻塞。

非阻塞运行:函数调用,无论条件是否满足,函数都会返回。
代码:

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<assert.h>

int main()
{
pid_t n = fork();
assert(n != -1);
//子进程
if(n==0)
{
printf("child will strat\n");
sleep(10);
printf("child will end\n");
}
else
{
//wait(NULL);//调用wait处理僵死进程,它会阻塞运行,子进程结束后,父进程才会开始运行
//printf("father start\n");
sleep(100);
//printf("father end\n");
}
}

在这里插入图片描述

5.孤儿进程

1.没有父进程的子进程,孤儿进程会被init接管

6.信号

1.信号:传递一种特殊信息的一种符号
2.操作系统中:操作系统预先定义好的某些特定的事件,信号可以被产生,也可以被接受。产生和接受的主体都是进程
3.信号的响应方式

  1. 默认
  2. 忽略
  3. 自定义

4.如何修改信号的响应方式:
typedef void (*Fun )(int);//类型
Fun signal (int signum,Fun fun);//修改信号响应方式函数

5.子进程结束后,发送一个信号到父进程,父进程接受到调用wait(不会阻塞)

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<assert.h>
#include<signal.h>

void fun(int sign)
{
wait(NULL);
}
int main()
{
pid_t n fork();
assert(n != -1);
//子进程
if(n==0)
{
printf("child will strat\n");
sleep(10);
printf("child will end\n");
}
else
{
//fun为函数地址
signal(SIGCHLD,fun,);//父进程接受子进程结束后发送的信号
//wait(NULL);//调用wait处理僵死进程,它会阻塞运行
printf("father start\n");
int i =0;
for(;i<100;++i)
{
sleep(1);
}
printf("father end\n");
}
}

参考资料:https://www.cnblogs.com/Anker/p/3271773.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值