一、共享内存实验
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);
}
}