进程通信实验报告
操作系统实验报告
任课教师 刘晓燕 姓名 赵九州 学号 1070410210 实验指导教师 刘晓燕
哈尔滨工业大学 年 6 月 8 日 2010
实验六 进程通信
一、实验目的
(1)学习Linux下用信号处理异步事件的方法 (2)掌握Linux下怎样通过管道实现进程通信
(3)了解Linux下进程间使用消息队列进行通信的基本知识
二、实验内容
(1)设计一个能响应键盘中断的程序。用signal系统调用让进程捕捉键盘上出的中断信号(Ctrl+C键)。练习使用kill命令向进程发信号。 (2)创建一对父子进程,这两个进程间利用管道传送数据和控制信息,要求父子进程能够连续向子进程传送数据,并且传送一定规模的数据,观察管道是否会溢出。结合内容(1)使用户可以用键盘中断终止数据传送。
(3)建立一个消息队列,创建两个进程,一个进程显示消息队列的状态,另一个进程从消息队列中读取消息,将读到的消息加入当前进程的信息后,再放入消息队列。
三、程序设计
主程序,准备消息队列,创建三个进程——两个模拟乘客、一个模拟汽车,等待子进程结束。
乘客进程:发送等待汽车的消息,接受上车的消息,接受下车的消息,发送离开消息。 汽车进程:接受乘客等待消息,发送接收乘客消息,发送下车的消息,接受离开消息。
四、调试过程与结果分析
第一个和第二个程序不同之处在于当第二个程序在前台运行时,第一次发送^C会打印捕获信号的语句。如果在后台运行,用kill命令直接被杀掉。
1)kill可向any prc发信号?
只可kill当前权限内的进程,向权限外的进程发送会被阻止。 3)没有亲缘关系进程间可使用消息队列通信? 应该可以在一定的限制下进行消息通讯
五、程序源代码
程序1.1
不能相应键盘中断的程序
#include
int main(){
int count;
printf("Start----------\n");
for (count=0;count
printf("%4d\n",count);
}
}
printf("End----------\n");
sleep(1);
程序1.2
可以响应Ctrl+C的程序
#include
void catcher(int sigtype){ printf("SC\t");
signal(SIGINT,SIG_DFL);
}
int main(){ int count;
printf("Start----------\n"); signal(SIGINT,catcher);
for (count=0;count
printf("End----------\n");
}
程序2
用消息队列通信的程序
#include #include #include #include #include #define MSGKEY 75
struct msgform { long mtype; //
int from;
//
} msg, msg1; int msgqid, i; void passenger () { pid_t pid = getpid (); int i, result;
for (i = 2; i >= 1; i--) { msg.mtype = 100; //sent to car
msg.from = pid;
if ((result = msgsnd (msgqid, &msg, sizeof (int), 0)) == 0)
printf ("passenger %d wait for car
\n", pid);
if ((result = msgrcv (msgqid, &msg1, sizeof (int), pid, 0)) != -1){
sleep (1);
fprintf (stdout, "passenger %d in
car %d \n", pid,msg1.from);
}
if ((result = msgrcv (msgqid, &msg, sizeof (int), pid, 0)) != -1){
sleep (1);
fprintf (stdout, "passenger %d get
message form car %d ,so he'll get out of\n", pid, msg.from);
}
msg.mtype = msg.from; msg.from = pid;
if ((result = msgsnd (msgqid, &msg, sizeof (int), 0)) == 0)
printf ("passenger %d say goodbye
to car %d \n", pid,msg.mtype);
} exit (0);
}
void car () { int i;pid_t pid = getpid (); int result;
int current_passenger;
for (i = 2; i >= 1; i--){ if ((result = msgrcv (msgqid, &msg, sizeof(int), 100, 0)) != -1)
printf ("(car %d)received a type %d
message from %d\n", pid, msg.mtype, msg.from);
current_passenger =
msg.mtype
=
msg.from;
msg.from = pid;
if ((result = msgsnd (msgqid, &msg, sizeof(int), 0)) == 0)
printf ("car %d tell %d passenger
to get on \n", pid,current_passenger);
sleep (2);
//travel
if ((result = msgsnd (msgqid, &msg, sizeof(int), 0)) == 0)
printf ("car %d tell %d passenger
to get off \n", pid,current_passenger);
if ((result = msgrcv (msgqid, &msg,
sizeof(int), pid, 0)) != -1)
printf ("car %d heard a bye message from passenger %d\n", pid,msg.from);
}
msgctl (msgqid, IPC_RMID, 0); exit (0);
}
void int_handler(int sigtype){ if (msgctl (msgqid, IPC_RMID, 0) == -1){
fprintf (stderr, "msgctl IPC_RMID failed
\n"); } else
fprintf(stderr, " delete the message queue\n");
}
int main () { int gflags; key_t key; char workdir[100];
signal(SIGINT, int_handler); 六、意见和建议
示例程序应该多加些注释,尤其是变量。 getcwd(workdir,100); key=ftok(workdir, MSGKEY); gflags=IPC_CREAT|IPC_EXCL;
if((msgqid = msgget (key, 0666 | gflags))== -1){ printf (" msgget failed with error\n"); exit(-1);
}
while ((i = fork ()) == -1); if (!i)passenger (); while ((i = fork ()) == -1); if (!i)passenger (); while ((i = fork ()) == -1); if (!i)car (); wait (0);
if (msgctl (msgqid, IPC_RMID, 0) == -1){ fprintf (stderr, "msgctl IPC_RMID failed \n");
}
}