实验1 进程管理
1、实验目的
(1)加深对进程概念的理解,明确进程和程序的区别。
(2)进一步认识并发执行的实质。
(3)分析进程争用资源的现象,学习解决进程互斥的
方法
快递客服问题件处理详细方法山木方法pdf计算方法pdf华与华方法下载八字理论方法下载
。
2、实验预备内容
(1)阅读linux的sched.h源码文件,加深对进程管理概念的理解。
(2)阅读linux的fork.c文件,分析进程的创建过程。
(3)相关函数
Fork()函数:用于创建一个新进程。
返回值:等于0,创建子进程,从子进程返回的ID值。大于0,从父进程返回的子进程的进程ID值;等于-1,创建新进程失败。
Wait()函数:控制父子进程之间的同步。
在父进程调用wait函数,则父进程被阻塞,等待子进程技术。当子进程结束时,产生一个终止状态字,系统会向父进程发出SIGCHILD信号,父进程收到后被唤醒。
调用格式为:
#include
#include
(pid_t) wait(int*statloc);
Exit()函数:进程终止。在正常终止时,exit()函数返回进程结束状态。
调用格式为:
#include
Void exit(int status);
其中,status为进程结束状态。
3、实验内容
(1)进程创建
编写一段程序,利用系统调用fork( )创建两个进程。当此程序运行时,在系统中有一个父进程和两个子进程活动。让每一个进程在屏幕上显示一个字符:父进程显示字符“a”;子进程分别显示字符“b”和字符“c”。
(2)进程控制
修改已经编号的程序,将每个进程输出一个字符改为每个进程输出一句话,在观察程序执行时屏幕上出现的现象,并分析原因。
如果在程序中使用系统调用lockf()来给每一个进程加锁,可以实现进程之间的互斥,观察并分析出现的现象。
参考程序1:
#include
Main()
{
Int p1,p2;
While ((p1=fork())= =-1);
If (p1= =0)
Putchar(‘b’);
Else
{
While ((p2=fork()= =-1);
If (p2= =0)
Putchar(‘c’);
Else
Putchar(‘a’);
}
}
分析执行结果及原因。
参考程序2:
#include
Main()
{
Int p1,p2;
While ((p1=fork()= =-1);
If (p1= =0)
For(i=0;i<50;i++)
Printf(“child%d\n”,i);
Else
{
While ((p2=fork()= =-1);
If (p2= =0)
For(i=0;i<50;i++)
Printf(“son%d\n”,i);
Else
For(i=0;i<50;i++)
Printf(“daughter%d\n”,i);
}
}
参考程序3:
#include
#include
Main()
{
Int p1,p2,I;
While ((p1=fork()= =-1);
If (p1= =0)
{
Lockf(1,1,0);
For(i=0;i<50;i++)
Printf(“child%d\n”,i);
Lockf(1,0,0);
}
Else
{
While ((p2=fork()= =-1);
If (p2= =0)
{
Lockf(1,1,0);
For(i=0;i<50;i++)
Printf(‘son%d\n”,i);
Lockf(1,0,0);
}
Else
{
Lockf(1,1,0);
For(i=0;i<50;i++)
Printf(“daughter%d\n”,i);
Lockf(1,0,0);
}
}
}
实验2 进程通信
一、实验目的
(1)理解进程处理信号的方法,使用用户自定义的信号处理程序。
(2)分析进程竞争资源现象,学习解决进程互斥的方法。
(3)了解linux系统中进程通信的基本原理。
二、预备内容
通过Linux提供的系统调用signal(),来说明如何执行一个预先安排好的信号处理函数。signal()的返回值是指向一个函数的指针,该函数的参数为一个整数。
#include
#include
#include
int ctrl_c_count=0;
void (* old_handler)(int);
void ctrl_c(int);
void main()
{
int c;
/*设置ctrl+c产生的信号SIGINT的处理程序为ctrl_c.取代系统原来默认的处理程序*/
old_handler=singal(SIGINT,ctrl_c);
/* 不断输入字符,同时按多次ctrl+c,直到按回车结束*/
while((c=getchar())!=’\n’));
printf(“ctrl_c_count=%d\n”,ctrl_c_count);
/*设置信号处理程序为原来的处理程序*/
(void) singal(SIGINT,old_hander);
/* 不断输入字符,ctrl+c结束*/
while ((c=getchar())!=’\n’));
}
/*对SIGINT信号的处理程序*/
void ctrl_c(int signum)
{
(void) signal(SIGINT,ctrl_c);
++ctrl_c;
}
程序说明:这个程序是从键盘获得字符,直到换行符为止,然后进入无限循环。这里,程序安排了捕获ctrl_c信号(SIGINT),并且利用SIGINT来执行一个ctrl_c的处理函数。当在键盘上敲入一个换行符时,SIGINT原来的操作(很可能是默认操作)才被恢复。Main()函数中的第一个语句完成设置信号处理程序:
old_handler = signal(SIGINT,ctrl_c);
signal()的两个参数是:信号值,这里是键盘中断信号SIGINT;以及一个指向函数的指针,这里是ctrl_c,当这个中断信号出现时,将调用该函数。Signal()调用返回旧的信号处理程序的地址,在此它被赋给变量older_handler,使得原来的信号处理程序稍后可以被恢复。
三、实验内容
1、软中断通信
编制一段程序,使用系统调用fork()创建两个子进程,再用系统调用signal()让父进程捕捉键盘上来的中断信号(即按ctrl+c键),当捕捉到中断信号后,父进程用系统调用kill()向两个子进程发出信号,子进程捕捉到信号后,分别输出下列信息后终止:
child process1 is killed by parent!
child process2 is killed by parent!
父进程等待两个子进程终止后,输出以下信息后终止:
parent process is killed!
2、进程的管道通信
编制一段程序,实现进程的管道通信。使用系统调用pipe()建立一条管道先。两个子进程p1和分别向管道各写一句话:
Child 1 process is sending a message!
Child 2 process is sending a message!
而父进程则从管道中读出来自于两个子进程的信息并显示在屏幕上。
3、消息通信
使用系统调用msgget( ), msgsnd( ), msgrcv( )及msgctl()编制一长度为1K的消息发送和接收的程序 。
〈程序设计〉
(1)为了便于操作和观察结果,用一个 程序为“引子”,先后fork( )两个子进程,SERVER和CLIENT,进行通信。
(2)SERVER端建立一个Key为75的消息队列,等待其他进程发来的消息。当遇到类型为1的消息,则作为结束信号,取消该队列,并退出SERVER 。SERVER每接收到一个消息后显示一句“(server)received”。
(3)CLIENT端使用Key为75的消息队列,先后发送类型从10到1的消息,然后退出。最后的一个消息,既是 SERVER端需要的结束信号。CLIENT每发送一条消息后显示一句“(client)sent”。
(4)父进程在 SERVER和 CLIENT均退出后结束。
参考程序:略。
4、共享存储区通信
使用系统调用shmget(),sgmat(),smgdt(),shmctl(),编制一个与上述相同功能的程序。参考程序1:
#include
#include
#include
#define SHMKEY 75
Int shmid,I;
Int *addr;
Void client()
{
Int I;
Shmid=shmget(SHMKEY,1024,0777); /*获取共享区,长度为1024*/