操作系统 实验二 进程与进程通信
文章目录
摘要
在本试验 PART1 中设计了一个程序,该程序创建一个子进程,使父子进程合作,协调地完成收发信号、打印目录功能。在该程序中使用了进程的睡眠、进程图象改换、父进程等待子进程终止、信号的设置与传送(包括信号处理程序)、子进程的终止等有关进程的系统调用。在本试验 PART2 中,分别利用 UNIX 的消息通信机制、共享内存机制(用信号灯实施进程间的同步和互斥)实现两个进程间的数据通信与简单的信息处理。
算法思想和概要设计
算法思想
PART1
父进程设置信号 SIGUSR1 的信号处理函数,子进程继承父进程的信号处理方式。子进程创建后进入 10 s 10s 10s 的低优睡眠;父进程先打印相关信息,在发送软中断信号前先进入 1 s 1s 1s 的低优睡眠,防止在子进程进入睡眠前就发送信号。父进程完成睡眠后将软中断信号传送给子进程,唤醒低优睡眠中的子进程,触发自定义的信号处理程序。之后子进程正常运行,执行图像改换,列出当前路径下的目录。父进程等待子进程终止。
PART2
消息通信
本部分分为 Server 进程和 Client 进程两个进程。Server 和 Client 通过同一个关键字获得相同消息队列的标识符。之后 Client 通过消息通信向 Server 发送信息,内容为自己的进程号,并接收 Server 通过消息通信返回的信息。Server 保持监听消息队列,收到 Client 发送的消息后就打印出来,并将消息经过一定处理后返回 Client。
共享内存
父进程创建 1 k b 1kb 1kb 大小的共享内存与同步信号灯组,得到共享内存标识符与信号灯组标识符。父进程把共享内存连接到当前进程的地址空间。由于本部分只有两个进程,所以任一信号灯的信号量不可能超过 1 1 1 ,因此信号灯组只需要两个信号灯,不需要互斥信号灯。信号灯组含读与写两个信号灯,写信号灯初始化为 1 1 1 ,读信号灯初始化为 0 0 0 。然后父进程创建子进程,子进程继承之前所述参数。之后父进程向共享内存中输入信息,子进程从共享内存中读出并处理信息,完成父子进程间的共享内存通信。
概要设计
以下将以流程图来展示对该程序分配与释放内存的过程概要设计。
PART1
PART2
消息通信
共享内存
数据结构与变量说明
消息缓冲区
struct msgtype{
long mtype; // 消息类型
int text; // 消息正文
};
信号灯组
typedef union semunion{
int val; /* Value for SETVAL */
struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */
unsigned short *array; /* Array for GETALL, SETALL */
struct seminfo *__buf; /* Buffer for IPC_INFO(Linux specific) */
}semunion;
源程序
PART1
主程序
#include <sys/types.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <unistd.h>
int main(){
int status;
pid_t pid;
void func();
signal(SIGUSR1, func); // 设置信号SIGUSR1的中断处理函数为func
while((pid = fork()) == -1); // 产生子进程
if(pid){
// 父进程
printf("It is the parent process.\n");
printf("Parent: will send signal.\n");
sleep(1); // 向子进程传送信号前先睡眠一秒,保证信号到达时子进程正在低优睡眠中
kill(pid, SIGUSR1); // 父进程向子进程传送SIGUSR1软中断信号
pid = wait(&status); // 父进程等待子进程终止
printf("Child process %d, status = %d.\n", pid, status);
}
else{
// 子进程
sleep(10);
printf("It is the child process.\n");
printf("Child: signal is received.\n");
execl("/bin/ls", "ls", "-l", (char*)0); // 进程图像改换,将子进程图像改换为ls命令
printf("execl error\n"); // 图像改换失败
exit(2);
}
printf("Parent process finish.\n");
}
void func(){
// 自己设置的信号SIGUSR1的中断处理函数
printf("It is a signal processing function.\n");
system("date");
}