【操作系统实验4】进程间通信:共享内存和消息传递

一、共享内存实验

1.实验目标

掌握子进程和父进程之间通过共享内存通信的原理

2.实验内容

1)思路

创建共享内存单元,子进程在内存单元写东西,然后父进程从内存单元里读东西,将结果打印出来.

2)代码

//sharedmem.c 文件
#include <stdio.h>

#include <sys/shm.h>

#include <unistd.h>

#include <sys/stat.h>

#include <sys/types.h>

#include <sys/wait.h>

 

int main()
{

        int segment_id;

        char * shared_memory;

        const int size = 4096;

       

        segment_id = shmget(IPC_PRIVATE, size, S_IRUSR | S_IWUSR);

        shared_memory = (char *) shmat(segment_id, NULL, 0);

 

        pid_t pid = fork();

        if (pid == 0) {

                 shared_memory = (char *) shmat(segment_id, NULL, 0);

                 printf("Child write: Hi There!\n");

                 sprintf(shared_memory, "Hi There!");

        }

        else {

                 wait(NULL);

                 printf("Parent read: %s\n", shared_memory);

                 shmdt(shared_memory);

                 shmctl(segment_id, IPC_RMID, NULL);

        }

       

        return 0;

}
 
 

3)过程及运行结果展示

编译并运行 sharedmem.c 程序
在这里插入图片描述

利用 sharedmem_test.sh 脚本运行 sharedmem 程序 1000次,查看运行结果
在这里插入图片描述
在这里插入图片描述

把sharedmem.c程序中的wait(NULL)注释掉,重新运行sharedmem_test.sh脚本程序,查看运行结果
在这里插入图片描述
在这里插入图片描述

3.实验结论

深入理解和掌握进程间通信的共享内存方式
创建好共享内存单元后,子进程在内存里写入,父进程从内存里读,若父进程等待子进程,即有wait(),则会正常显示子进程先写父进程后读;若父进程不等待子进程,即没有wait(),则会出现父进程在子进程写入之前读出空的结果,这个是因为在没有等待的情况下父进程和子进程的运行顺序无法确定,

二、消息传递实验

1.实验目标

了解和掌握进程间通信的消息传递方式
掌握进程之间如何通过消息队列进行通信

2.实验内容

1)思路

让父进程创建两个子进程P1和P2,并使子进程P1和P2通过消息队列相互通信,发送消息,发送 512字节消息。

2)代码

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <stropts.h>
#include <time.h>
#include <strings.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include<sys/wait.h>
#define MSGKEY 67

struct msg
{
	long msg_types;
	char msg_buf[512];
};

int msgqid;
int main()
{
	struct msg msg1,msg2;
	int p1,p2,pid1,pid2,*pint1,*pint2;
	while((p1=fork())==-1);
	if(p1==0)
	{
		msgqid=msgget(MSGKEY,0777|IPC_CREAT);
		strcpy(msg1.msg_buf,"Hello,P2");
		msg1.msg_types=1;
		msgsnd(msgqid,&msg1,512,0);
		sleep(3);
		msgrcv(msgqid,&msg1,512,1,0);
		printf("P1 receive from P2:%s\n",msg1.msg_buf);
		msgctl(msgqid,IPC_RMID,0);
		exit(0);
	}
	else
	{
		while((p2=fork())==-1);
		if(p2==0)
		{
		//	wait(NULL);
			msgqid=msgget(MSGKEY,0777|IPC_CREAT);
			msgrcv(msgqid,&msg2,512,1,0);
			printf("P2 receive from P1:%s\n",msg2.msg_buf);
			msg2.msg_types=1;
			strcpy(msg2.msg_buf,"Hi,P1");
			msgsnd(msgqid,&msg2,512,0);
			exit(0);
		}
		//wait(0);
		//wait(0);
	}
}

3)过程及运行结果展示

编译运行messagepass.c 程序,并查看结果
在这里插入图片描述

基于例子代码,编写如下程序:让父进程创建两个子进程 P1 和 P2,并两个子进程 P1 和 P2之间通过消息队列相互通信,发送 512字节消息。
编写的程序见上页。

进程间消息传递的实现
在这里插入图片描述

3.实验结论

通过fork()创建两个子进程,利用msgsnd()向消息队列发送消息,利用msgrcv()来从消息队列中接受消息,最后msgctl()撤销消息队列。
消息传递的消息通信是可以用于所有进程之间通信的。

附录:代码

//sharedmem.c 文件
#include <stdio.h>

#include <sys/shm.h>

#include <unistd.h>

#include <sys/stat.h>

#include <sys/types.h>

#include <sys/wait.h>

 

int main()
{

        int segment_id;

        char * shared_memory;

        const int size = 4096;

       

        segment_id = shmget(IPC_PRIVATE, size, S_IRUSR | S_IWUSR);

        shared_memory = (char *) shmat(segment_id, NULL, 0);

 

        pid_t pid = fork();

        if (pid == 0) {

                 shared_memory = (char *) shmat(segment_id, NULL, 0);

                 printf("Child write: Hi There!\n");

                 sprintf(shared_memory, "Hi There!");

        }

        else {

                 wait(NULL);

                 printf("Parent read: %s\n", shared_memory);

                 shmdt(shared_memory);

                 shmctl(segment_id, IPC_RMID, NULL);

        }

       

        return 0;

}
 
 
 
 
 
//sharedmem_test.sh 文件
#!/bin/bash

for ((i = 1; $i <= 1000; i++));

do

    echo $i

    ./sharedmem

done





//messagepass.c 文件
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <stropts.h>
#include <time.h>
#include <strings.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/msg.h>

struct msg {

    long msg_types;

    char msg_buf[511];

};

 

int main (void) {

        int qid, pid, len;

        struct msg pmsg;

        sprintf ( pmsg.msg_buf, "Hello! This is :%d\n", getpid());

        len = strlen ( pmsg.msg_buf );

       

        if ( (qid = msgget( IPC_PRIVATE, IPC_CREAT | 0666)) < 0 ) {

                 perror( "msgget");

                 exit (1);

        }

       

        if ( (msgsnd(qid, &pmsg, len, 0)) < 0) {

                 perror( “msgsnd”);

                 exit(1);

        }

       

        printf("Send a message to the queue successfully : %d\n", qid);

        exit(1);

}
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <stropts.h>
#include <time.h>
#include <strings.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include<sys/wait.h>
#define MSGKEY 67

struct msg
{
	long msg_types;
	char msg_buf[512];
};

int msgqid;
int main()
{
	struct msg msg1,msg2;
	int p1,p2,pid1,pid2,*pint1,*pint2;
	while((p1=fork())==-1);
	if(p1==0)
	{
		msgqid=msgget(MSGKEY,0777|IPC_CREAT);
		strcpy(msg1.msg_buf,"Hello,P2");
		msg1.msg_types=1;
		msgsnd(msgqid,&msg1,512,0);
		sleep(3);
		msgrcv(msgqid,&msg1,512,1,0);
		printf("P1 receive from P2:%s\n",msg1.msg_buf);
		msgctl(msgqid,IPC_RMID,0);
		exit(0);
	}
	else
	{
		while((p2=fork())==-1);
		if(p2==0)
		{
		//	wait(NULL);
			msgqid=msgget(MSGKEY,0777|IPC_CREAT);
			msgrcv(msgqid,&msg2,512,1,0);
			printf("P2 receive from P1:%s\n",msg2.msg_buf);
			msg2.msg_types=1;
			strcpy(msg2.msg_buf,"Hi,P1");
			msgsnd(msgqid,&msg2,512,0);
			exit(0);
		}
		//wait(0);
		//wait(0);
	}
}

  • 5
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值