您的当前位置:首页正文

进程实验-进程间通信(管道、消息、共享内存、软中断)

2020-05-25 来源:汇智旅游网
 1

进程实验3 Linux 进程间通信

一、 软中断信号的处理,实现同一用户的各进程之间的通信。

相关的系统调用

 kill(pid ,sig):发送信号

 signal(sig, func):指定进程对信号sig的处理行为是调用函数func。

程序清单

#include

#include

#include

void waiting();

void stop();

int wait_mark;

main()

1

2

{

int p1,p2;

while((p1=fork())==-1);

if(p1>0)

{

while((p2=fork())==-1);

if(p2>0)

{ printf(\"parent\\n\");

/*父进程在此完成某个操作、或接收到用户从键盘输入的特殊按键命令后发出下面的信号。这里省略。 */

kill(p1,16);

kill(p2,17);

wait(0);

wait(0);

2

printf(\"parent process id killed! \\n\");

exit(0);

}

else/* p2==0*/

{

printf(\"p2\\n\");

wait_mark=1;

signal(17,stop);

waiting();

printf(\"child process 2 is killed by parent! \\n\");

exit(0);

}

}

3

3

else/*p1==0*/

{

printf(\"p1\\n\");

wait_mark=1;

signal(16,stop);

waiting();

printf(\"child process 1 is kelled by parent! \\n\");

exit(0);

}

}

void waiting()

{while(wait_mark!=0);}

void stop()

4

4

5

{wait_mark=0;}

输入并运行此程序,分析程序的运行结果。

二、 消息的创建、发送和接收

多个进程通过访问一个公共的消息队列来交换信息

消息队列: 即消息的一个链表

任何进程都可以向消息队列中发送消息(消息类型及正文),其它进程都可以从消息

队列中根据类型获取相应的消息

相关的系统调用 头文件:#include

 打开或创建消息队列:int msgget(key_t key, int msgflg);

 key:消息队列的键

 IPC_PRIVATE: 创建一个私有的消息队列

 其它:可被多个进程使用的消息队列

 msgflg:设置操作类型及访问权限IPC_CREAT / IPC_EXCL

获得或设置消息队列属性:int msgctl( int msgid, int cmd, struct

5

msqid_ds *data);

 发送消息:int msgsnd(int msgid, const void *msgp,

 size_t msgsize, int flags);

 参数

 msgid:消息队列标识符id

 msgp:指针,用户自定义缓冲区,可定义成结构体类型,包含两项 mtype;代表消息类型

 char mtext[MTEXTSIZE];消息正文

 msgsize:要发送消息正文的长度

 mflags:标志,若设置IPC_NOWAIT则不等待 息发出就返回

 返回值:成功返回0,错误返回-1(置errno)

 接收消息int msgrcv(int msgid, void *msgp, size_t mtexsize, msgtype, int flags);

参数:与msgsnd类似

6

long

long

6

7

 msgtype

 >0:只接收指定类型消息的第一个

 ==0:不管什么消息类型都读取队列中第一个数据

 <0:接收等于或小于其绝对值的最低类型的第一个,如有5、17三类,若为-6,则获取类型5的。

 返回值

 成功:返回消息正文字节数

 错误:返回-1(置errno)

程序清单

#include

#include

#include

#include

#define MSGKEY 75

6、

7

struct msgform

{

long mtype;

char msgtext[1030];

}msg;

int msgqid,i;

void CLIENT()

{

int i; char string_i[5];

msgqid=msgget(MSGKEY,0777);

for(i=10;i>=1;i--)

{

msg.mtype=i;

8

8

printf(\"(client)sent\\n\");

sprintf(msg.msgtext,\"the content of message \");

sprintf(string_i, \"%d\

strcat(msg.msgtext,string_i);

strcat(msg.msgtext,\"\\n\");

msgsnd(msgqid,&msg,1030,0);

}

exit(0);

}

void SERVER()

{

msgqid=msgget(MSGKEY,0777|IPC_CREAT);

do

9

9

{

msgrcv(msgqid,&msg,1030,0,0);

printf(\"(server)received message %d \\n\

printf(“%s\\n\

}while(msg.mtype!=1);

msgctl(msgqid,IPC_RMID,0);

exit(0);

}

main()

{

while((i=fork())==-1);

if(!i) SERVER();

while((i=fork())==-1);

10

10

11

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 shmflg);

 参数

key:键值

11

12

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表示由系统安

排。

flags:对该内存的段设置是否只读 (SHM_RDONLY), 默认是读

写。

12

 返回值

成功:进程中该内存段的地址

错误: -1

程序清单:

#include

#include

#include

#include

#define SHMKEY 75

int shmid,i;

int *addr;

void CLIENT()

{

13

13

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(\"client i: %d\\n\

}

exit(0);

}

void SERVER()

14

14

{

shmid=shmget(SHMKEY,1024,0777|IPC_CREAT);

addr=shmat(shmid,0,0);

do

{

*addr=-1;

while(*addr==-1);

printf(\"(server)received ,\" );

printf(\"server *addr %d\\n\

}while(*addr);

shmctl(shmid,IPC_RMID,0);

exit(0);

}

15

15

16

main()

{

while((i=fork())==-1);

if(!i)SERVER();

while((i=fork())==-1);

if(!i) CLIENT();

wait(0);

wait(0);

}

编辑并运行程序,并分析程序的运行结果。

在此基础上对程序进行修改:使得每次循环中:CLIENT向共享区发送10个整数, SERVER从共享区接收10个整数、并输出。

16

因篇幅问题不能全部显示,请点此查看更多更全内容