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.信号的响应方式:
- 默认
- 忽略
- 自定义
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");
}
}