实验内容:
1.编写一段程序,创建一个共享存储区,大小是4个字节(1个整型数的大小)。创建一个子进程,然后父、子进程各自独立运行。父进程从标准输入设备中输入一个数,把这个数写入共享存储区;子进程把这个数从共享存储区中读出来,并输出到标准输出设备中。
(提示:初始时,可以把共享存储区的数值赋值为-1。父进程执行,把用户输入的数据写入共享存储区,(则此时共享存储器中的数值已不为-1)。子进程先循环判断如果共享存储区中的数值为-1,则循环什么都不做,只有当共享存储区中的数值不为-1时,才从循环跳出,然后从共享存储区中读出这个数据,输出到屏幕中。)
观察程序输出的结果,并做出合理的解释。
可能用到的系统调用:shmget( )、shmat( )、shmdt( )、shmctl( )
掌握以上系统调用的使用方法及其功能,理解共享存储区通信原理。
程序代码如下:
#include<iostream>
#include<sys/wait.h>
#include<sys/ipc.h> // shmget的头文件
#include<sys/shm.h> // shmat shmget shmctl 的头文件
#include<sys/types.h> // shmat,shmctl 的头文件
using namespace std;
int main()
{
int shmid;
int pid;
int *p_addr , *c_addr;
// 得到一个共享内存标识符或创建一个共享内存对象并返回共享内存标识符
// (IPC_PRIVATE):会建立新共享内存对象
// 1024: 新建的共享内存大小,以字节为单位
// shmflg: 取共享内存标识符,若不存在则函数会报错
// IPC_CREAT|IPC_EXCL:如果内核中不存在键值与key相等的共享内存,
// 则新建一个消息队列;如果存在这样的共享内存则报错
// 成功:返回共享内存的标识符 出错:-1,错误原因存于error中
// 0600 存取权限
shmid = shmget(IPC_PRIVATE, 1024, IPC_CREAT|IPC_EXCL|0666);
if( shmid == -1)
{
cout<<"生成共享存储区失败!";
exit(1);
}
pid = fork();
if( pid > 0)
{
/*
* void *shmat(int shmid, const void *shmaddr, int shmflg)
* shmid:共享内存标识符
* 2: 指定共享内存出现在进程内存地址的什么位置,直接指定为NULL让内核自己决定一个合适的地址位置
* 3:SHM_RDONLY:为只读模式,其他为读写模式
* 成功:附加好的共享内存地址 出错:-1,错误原因存于error中
*/
p_addr = (int*)shmat( shmid ,0 , 0);
*p_addr = -1;
cout<<"父进程:输入一个数字:"<<endl;
cin>>*p_addr;
wait(NULL);
}
else if(pid == 0){
c_addr = (int*)shmat( shmid , 0 ,0);
*c_addr = -1;
while( ( *c_addr ) == -1 );
cout<<"子进程:这个数字是"<< *c_addr<<endl;
}else{
cout<<"Fork Error!"<<endl;
}
/*
* int shmctl(int shmid, int cmd, struct shmid_ds *buf)
* shmid:共享内存标识符
* 2 cmd : IPC_SET:改变共享内存的状态,把buf所指的shmid_ds结构中的uid、gid、mode复制到共享内存的shmid_ds结构内
* IPC_RMID:删除这片共享内存 IPC_STAT:得到共享内存的状态,把共享内存的shmid_ds结构复制到buf中
* 3:buf:共享内存管理结构体。具体说明参见共享内存内核结构定义部分
* 成功:0 出错:-1,错误原因存于error中
*/
shmctl( shmid ,IPC_RMID ,0); //完成对共享内存的控制
return 0;
}
程序运行截图如下: