当前位置:   article > 正文

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);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

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);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

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");
}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

在这里插入图片描述

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");
}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36

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

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/爱喝兽奶帝天荒/article/detail/883002
推荐阅读
相关标签
  

闽ICP备14008679号