1、11进程实验 3 Linux 进程间通信一、 软中断信号的处理,实现同一用户的各进程之间的通信。 相关的系统调用 kill(pid ,sig):发送信号 signal(sig, func):指定进程对信号 sig 的处理行为是调用函数 func。 程序清单#include #include #include void waiting();void stop();int wait_mark;main()int p1,p2;while(p1=fork()=-1);if(p10)while(p2=fork()=-1);if(p20) printf(“parentn“);/*父进程在此完成某个操作、或
2、接收到用户从键盘输入的特殊按键命令后发出下面的信号。这里省略。 */kill(p1,16);kill(p2,17);wait(0);wait(0);printf(“parent process id killed! n“);exit(0);else/* p2=0*/printf(“p2n“);wait_mark=1;signal(17,stop);waiting();printf(“child process 2 is killed by parent! n“);exit(0);else/*p1=0*/ 22printf(“p1n“);wait_mark=1;signal(16,stop);w
3、aiting();printf(“child process 1 is kelled by parent! n“);exit(0);void waiting()while(wait_mark!=0);void stop()wait_mark=0; 输入并运行此程序,分析程序的运行结果。二、 消息的创建、发送和接收 多个进程通过访问一个公共的消息队列来交换信息 消息队列: 即消息的一个链表 任何进程都可以向消息队列中发送消息(消息类型及正文) ,其它进程都可以从消息队列中根据类型获取相应的消息 相关的系统调用 头文件:#include 打开或创建消息队列:int msgget(key_t key
4、, int msgflg); key:消息队列的键 IPC_PRIVATE: 创建一个私有的消息队列 其它:可被多个进程使用的消息队列 msgflg:设置操作类型及访问权限 IPC_CREAT / IPC_EXCL 获得或设置消息队列属性:int msgctl( int msgid, int cmd, struct msqid_ds *data); 发送消息:int msgsnd(int msgid, const void *msgp, size_t msgsize, int flags); 参数 msgid:消息队列标识符 id msgp:指针,用户自定义缓冲区,可定义成结构体类型,包含两项
5、 long mtype;代表消息类型char mtextMTEXTSIZE;消息正文 msgsize:要发送消息正文的长度 mflags:标志,若设置 IPC_NOWAIT 则不等待 消息发出就返回 返回值:成功返回 0,错误返回-1(置 errno) 接收消息 int msgrcv(int msgid, void *msgp, size_t mtexsize, long msgtype, int flags);33 参数:与 msgsnd 类似 msgtype 0:只接收指定类型消息的第一个 =0:不管什么消息类型都读取队列中第一个数据 #include #include #include
6、#define MSGKEY 75struct msgformlong mtype;char msgtext1030;msg;int msgqid,i;void CLIENT()int i; char string_i5;msgqid=msgget(MSGKEY,0777);for(i=10;i=1;i-)msg.mtype=i;printf(“(client)sentn“);sprintf(msg.msgtext,“the content of message “);sprintf(string_i, “%d“,i );strcat(msg.msgtext,string_i);strcat(
7、msg.msgtext,“n“);msgsnd(msgqid,exit(0);void SERVER()msgqid=msgget(MSGKEY,0777|IPC_CREAT);domsgrcv(msgqid,printf(“(server)received message %d n“, msg.mtype );44printf(“%sn“, msg.msgtext );while(msg.mtype!=1);msgctl(msgqid,IPC_RMID,0);exit(0);main()while(i=fork()=-1);if(!i) SERVER();while(i=fork()=-1)
8、;if(!i) CLIENT();wait(0);wait(0);编辑并运行程序,并分析程序的运行结果。思考题:符号常量 MSGKEY 有什么作用?server 和 client 不使用同一个MSGKEY 会出现什么问题?程序扩展:client 和 server 之间怎样通过软中断信号控制进程的推进速度,使得client 每发送一个消息,server 就接收一个消息,然后 client 再发送下一个消息?三、 共享存储区的创建、发送和接收同一系统中的几个进程可共享某块物理内存。include 打开或创建创建共享区:int shmget(key_t key, size_t size, int s
9、hmflg); 参数 key:键值 IPC_PRIVATE: 创建一个私有的 shm 其它:非 IPC_PRIVATE 整数值。 size:指明 shm 的大小,若 shm 已经存在,则 size 应为 0 shmflg:设置访问权限及 IPC_CREAT / IPC_EXCL 返回值 成功:该 shm 的 id,当前进程是其 拥有者及创建者错误:-1 将共享内存连接到进程中:void *shmat(int shmid, const void *shmaddr, int flags); 参数 shmid:共享内存标识符 id shmaddr:进程映射内存段的地址,可指定,但一般设为 NULL
10、表示由系统安排。 flags:对该内存的段设置是否只读 (SHM_RDONLY), 默认是读写。 返回值 成功:进程中该内存段的地址55 错误: -1 程序清单:#include #include #include #include #define SHMKEY 75int shmid,i;int *addr;void CLIENT()int i;shmid=shmget(SHMKEY,1024,0777);addr=shmat(shmid,0,0);for(i=5;i=0;i-)while(*addr!=-1);printf(“(client)sent, “);*addr=i;printf(
11、“client i: %dn“,i);exit(0);void SERVER()shmid=shmget(SHMKEY,1024,0777|IPC_CREAT);addr=shmat(shmid,0,0);do*addr=-1;while(*addr=-1);printf(“(server)received ,“ );printf(“server *addr %dn“, *addr);while(*addr);shmctl(shmid,IPC_RMID,0);exit(0);66main()while(i=fork()=-1);if(!i)SERVER();while(i=fork()=-1);if(!i) CLIENT();wait(0);wait(0);编辑并运行程序,并分析程序的运行结果。在此基础上对程序进行修改:使得每次循环中:CLIENT 向共享区发送 10 个整数, SERVER 从共享区接收 10 个整数、并输出。