前言
这是大三上学期的操作系统的实验,过程感触比较深,但是同时又感觉自己学的很浅薄,所以就将这个自己理解的过程与源码发上来。做为笔记以及方便以后再做查看。如果有实验需求的也可以跑一下这个程序和你所理解的fork()以及进程通信有什么区别。
分块解释
1.fork()实现(部分)
- 代码如下
void winfork()//fork函数模拟--行为模式:子进程就返回0,非子进程返回该进程的子进程的pid
{
/**********************判断结构***************/
if(num==0)
{
printf("当前没有运行的进程,无法进行fork()行为\n");
return;
}
if (num==20)
{
printf("fork error!");
return;//内存没空间创建子进程
}
/*******************************************/
/**********模拟复制内容部分*********/
printf("\n请输入要执行fork()的进程的pid值:\n"); //选择父进程
scanf("%d",&pid); //此时的pid是父进程的pid
sign=0;
for(i=0;i<20;i++)
{
if(RAM[i].pid==pid) //在20个内存里查找pid符合条件的父进程
{
if(RAM[i].child_sign==0) //pid符合条件且其下没有子进程
{
printf("\n请输入子进程的pid\n"); //对新建的子进程的pid赋值
scanf("%d",&RAM[num+1].pid);
for(j=0;j<num;j++) /*判断是否之前已存储相同pid进程*/
if(RAM[j].pid==RAM[num+1].pid)
{
printf("\n该进程pid已存在于内存中");
return;
}
RAM[num+1].priority=RAM[i].priority;
RAM[num+1].size=RAM[i].size;
strcpy(RAM[num+1].task,RAM[i].task);
RAM[num+1].state=1; /*将进程状态设为1,表示在内存中*/
RAM[num+1].child_sign=0;
RAM[i].child_sign=RAM[num+1].pid;
if(RAM[i].fds_0!=2){
//权限同步
RAM[num+1].fds_0=RAM[i].fds_0;
RAM[num+1].fds_1=RAM[i].fds_1;
}
num++;/*内存中进程数目加一*/
sign=1;
return;
}
}
}
if(sign==0) printf("\n执行失败!\n" );
}
我做的只是一个完成度很低的模拟(能力不足),这里我主要是模拟了fork会使得子进程基础父进程所有状态(除进程标识符和父子标志外)相同,并且对于父子进程标志会有更改。
RAM[num+1].child_sign=0;
RAM[i].child_sign=RAM[num+1].pid;
以及权限同步
RAM[num+1].fds_0=RAM[i].fds_0;
RAM[num+1].fds_1=RAM[i].fds_1;
2.进程通信模拟(部分)
以下流程有关于函数实现pipe建立管道后建立子进程,并关闭父进程的
管道本质为内核缓冲区,用户态来看是一个伪文件
由于是伪文件,所以对于管道有两个文件描述符引用,一个表示读端,一个表示写端
管道是基于字节流实现通信的
管道依赖于文件系统,其生命周期随进程
管道本身自带同步互斥
fork()进程的时候,子进程会继承父进程的管道与其描述符
单方向流动,半双工通信类型,且只作用于有血缘关系的进程之间
代码如下:
void communication()
{
if(num==0)
{
printf("当前没有运行的进程,无法进行进程通信行为\n");
return;
}
int f_pid,c_pid;//进行进程通信的进程的id(父子)
char buf[20];//缓存区
printf("\n 请输入父进程 pid\n");
scanf("%d",&f_pid);//获取父进程pid
/************对父进程的确认**********/
for(i=0;i<20;i++)
{
if(RAM[i].pid==f_pid) //在20个内存里查找pid符合条件的父进程
{
if(RAM[i].child_sign==0) //pid符合条件且其下没有子进程建立管道
{
if (num==20)return;//无进程空间建立子进程//
RAM[i].fds_0=1; //激活读取权限
printf("进程(pid=%d)的读取权限已授权,",RAM[i].pid);
RAM[i].fds_1=1; //激活写入权限
printf("进程(pid=%d)的写入权限已授权\n",RAM[i].pid);
/******为进程建立子进程并激活权限***********/
printf("\n请输入子进程的pid\n"); //对新建的子进程的pid赋值
scanf("%d",&RAM[num+1].pid);
for(j=0;j<num;j++) /*判断是否之前已存储相同pid进程*/
if(RAM[j].pid==RAM[num+1].pid)
{
printf("\n该pid已被占用");
return;
}
RAM[num+1].priority=RAM[i].priority;
RAM[num+1].size=RAM[i].size;
strcpy(RAM[num+1].task,RAM[i].task);
RAM[num+1].state=1; /*将进程状态设为1,表示在内存中*/
RAM[num+1].child_sign=0;
RAM[i].child_sign=RAM[num+1].pid;
if(RAM[i