栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

ZUCC

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

ZUCC

lab7进程通信—共享内存 一.利用共享内存实现生产者/消费者问题的解决方案

1.代码

#include
#include
#include
#include
#include
#include
#include

#define KEY 1234		//键
#define SIZE 1024		//欲建立共享内存的大小

int main(){
	int shmid;
	char *shmaddr;
	struct shmid_ds buf;	
	shmid=shmget(KEY,SIZE,IPC_CREAT|0600);		//建立共享内存
	
	if(shmid==-1){
		printf("create share memory failed:%s",strerror(errno));
		return 0;
	}
	if(fork()==0){
		sleep(2);							//子进程
		shmaddr=(char*)shmat(shmid,NULL,0);//系统自动选择一个地址来链接
		if(shmaddr==(void*)-1){
			printf("connect the share memory failed:%s",strerror(errno));
			return 0;
		}
		strcpy(shmaddr,"heelo i am huijn");
		shmdt(shmaddr);			//断开共享内存
		exit(0);
	}
	else{
		wait(0);					//父进程
		shmctl(shmid,IPC_STAT,&buf);	//获取共享内存相关信息
		printf("size of the share memory:shm_segsz=%dbytesn",buf.shm_segsz);
		printf("process id of the creator:shm_cpid=%dn",buf.shm_cpid);
		printf("process id of the last operator:shm_lpid=%dn",buf.shm_lpid);
		shmaddr=(char*)shmat(shmid,NULL,0);//系统自动选择一个地址连接
		if(shmaddr==(void*)-1){
			printf("connect the share memory failed:%s",strerror(errno));
			return 0; 
		}
		printf("print the content of the share memory:t");
		printf("%sn",shmaddr);
		shmdt(shmaddr);				//断开共享内存
		shmctl(shmid,IPC_STAT,&buf);//取得共享内存相关信息
		printf("process id of the last operator:shm_lpid =%dn",buf.shm_lpid);
		//当不在有任何其他相关进程使用该共享内存时系统自动销毁它
		shmctl(shmid,IPC_RMID,NULL);
	}
} 

运行注意:

1. ./t &
2. ctr+c 

2)删除注释1,重新编译运行程序,理解变和不变的部分

1.不删注释1:[1]+ 完成				ipcs -m -t:无最新共享内存信息
  删除注释1:[1]+ 退出  47			ipcs -m -t:有最新共享内存消息

不删注释:

删除注释:

3)删除注释1,重新编译运行程序,利用ipcs查看共享内存的相关信息

删除注释:



二.利用共享内存机制,在两个并发程序中,传递数据

1.代码:

//write.c
#include
#include
#include
#include
#include
#include

#define SHMSZ 27

int main(){
	char c;
	int shmid;
	key_t key;
	char *s,*shm;
	key=5679;
	if((shmid=shmget(key,SHMSZ,IPC_CREAT|0666))<0){
		perror("shmget");
		exit(1);
	}
	if((shm=shmat(shmid,NULL,0))==(char*)-1){
		perror("shmat");
		exit(1);
	}
	s=shm;
	for(c='a';c<'z';c++){
		*s++=c;
//		sleep(1);
	}
	*s='';
} 
//read.c
#include
#include
#include
#include
#include
#include

#define SHMSZ 27

int main(){
	int shmid;
	key_t key;
	char *s,*shm;
	key=5679;
	
	if((shmid=shmget(key,SHMSZ,0666))<0){			//
		perror("shmget");				//
		exit(1);
	}
	if((shm=shmat(shmid,NULL,0))==(char*)-1){			//
		perror("shmat");	
		exit(1);
	}
	for(s=shm;*s!='';s++)
		putchar(*s);
	putchar('n');					///''  (x:"")
	exit(0);
}

通过两个终端分别运行写入进程和读出进程,观察进程并发执行结果:

注意:1.在运行读和写程序后要清理共享内存
	 2.清理的方式:ipcs -m -t  获得共享内存的信息
	 			 ipcrm  -m shmid  删除该共享内存信息 

2)两个并发进程的启动顺序对程序运行有没有影响?

有影响,先写再读才有输入结果嘛

先写再读:

先读再写:

注意:因为程序没有配置删除共享内存代码,所以需要手动删除
1.ipcs -m -t
2.ipcrm -m shmid (删除最近时间创立的几个)

3)将注释1换成{*s++=c;sleep(1)),降低写入进程写数据的速度,观察对读出进程的影响?这说明共享内存没有提供同步机制,有可能导致数据缺失

注意:因为程序没有配置删除共享内存代码,所以需要手动删除
1.ipcs -m -t
2.ipcrm -m shmid (删除最近时间创立的几个)
3. ./writer(另一个终端)
4. ./reader(另一个终端)

如图:



三.利用共享内存实现生产者/消费者问题

1.代码:

//The second program is the producer and allow us to enter data for consumers
 #include
 #include
 #include
 #include
 #include
 #include
 #include
 
 #define TEXT_SZ 2048
 
 struct shared_use_st{
 	int written_by_you;
 	char some_text[TEXT_SZ];
 };
 
 int main(){
 	int running=1;
 	void *shared_memory=(void*)0;
 	struct shared_use_st *shared_stuff;
 	char buffer[BUFSIZ];
 	int shmid;
 	
 	shmid=shmget((key_t)1234,sizeof(struct shared_use_st),0666|IPC_CREAT);		//
 	if(shmid==-1){
 		fprintf(stderr,"shmget failedn");
 		exit(EXIT_FAILURE);
	}
	shared_memory=shmat(shmid,(void*)0,0);		//
	if(shared_memory==(void*)-1){
		fprintf(stderr,"shmat failedn");
		exit(EXIT_FAILURE);
	} 
	shared_stuff=(struct shared_use_st*)shared_memory;		//
	while(running){
//		while(shared_stuff->written_by_you==1){
//			sleep(1);
//			printf("waiting for client...n");
//		}
		printf("Enter som text:");
		fgets(buffer,BUFSIZ,stdin);
		strncpy(shared_stuff->some_text,buffer,TEXT_SZ);
		shared_stuff->written_by_you=1;
		if(strncmp(buffer,"end",3)==0)			//
			running=0;
	} 
	if(shmdt(shared_memory)==-1){				//
		fprintf(stderr,"shmdt failedn");		//
		exit(EXIT_FAILURE);			//
	}
	exit(EXIT_SUCCESS);			//
 }
#include
#include
#include
#include
#include
#include
#include
 
#define TEXT_SZ 2048
 
struct shared_use_st{
 	int written_by_you;
 	char some_text[TEXT_SZ];
};
 
int main(){
 	int running=1;
 	void *shared_memory=(void*)0;
 	struct shared_use_st *shared_stuff;
 	int shmid;

	srand((unsigned int )getpid()); 	
 	shmid=shmget((key_t)1234,sizeof(struct shared_use_st),0666|IPC_CREAT);
 	if(shmid==-1){
 		fprintf(stderr,"shmget failedn");
 		exit(EXIT_FAILURE);
	}
	
//We now make the shared memory accessible to the program
	shared_memory=shmat(shmid,(void*)0,0);
	if(shared_memory==(void*)-1){
		fprintf(stderr,"shmat failedn");
		exit(EXIT_FAILURE);
	} 
	
	
	
	shared_stuff=(struct shared_use_st*)shared_memory;
	shared_stuff->written_by_you=0;
	while(running){
		if(shared_stuff->written_by_you){
			printf("You wrote:%s",shared_stuff->some_text);
			sleep(rand()%4);
			shared_stuff->written_by_you=0;
			if(strncmp(shared_stuff->some_text,"end",3)==0)
				running=0;
		}
	}
	
//Lastly,the shared memory is detached and then deleted	
	if(shmdt(shared_memory)==-1){
		fprintf(stderr,"shmdt failedn");
		exit(EXIT_FAILURE);
	}
	if(shmctl(shmid,IPC_RMID,0)==-1){
		fprintf(stderr,"shmctl(IPC_RMID)failedn");
		exit(EXIT_FAILURE);
	}
	exit(EXIT_SUCCESS);
 }

编译链接后,分别通过两个终端运行生产者,消费者进程,观察执行结果

2)确定两个并发进程的启动顺序

先消费,再生产
shared_stuff->written_by_you=0;在消费者中初始化

3)删除蓝色标记的代码,看对并发进程有什么影响?

1.write端“Enter some text""waiting for client"无输出

4)理解share_stuff->written_by_you在并发程序中的作用,效果如何?效率如何?

条件判断:等待消费者消费前生产者一直输出"waiting for client"


四.编写程序

1.编写程序,实现父进程和子进程通过共享内存交换信息。要求:子进程先将子进程号写入共享内存,父进程将内容读出并显示。随后,父进程将父进程号写入共享内存,子进程读出并显示。使用完毕,父进程注销共享内存。

代码:

#include
#include
#include
#include
#include
#include
#include

#define KEY 1234		//键
#define SIZE 1024		//欲建立共享内存的大小

void intToString(int a,char b[]){
	int i,m;
	char c[20];
	for(i=1;a/i!=0;i*=10);
	m=i/10;
//		printf("m %dn",m);
	
	for(i=0;m!=0;i++,m/=10){
		c[i]=(char)(48+a/m);		//ASCll码 
		a-=a/m*m;	
	}
	c[i+1]='';
//		printf("%sn",c);

	for(i=0;c[i]!='';i++)
		b[i]=c[i];	
} 
 
int main(){
	int shmid;
	char *shmaddr;
	int p1;
	struct shmid_ds buf;	
	shmid=shmget(KEY,SIZE,IPC_CREAT|0600);		//建立共享内存
	
	if(shmid==-1){
		printf("create share memory failed:%s",strerror(errno));
		return 0;
	}
	if((p1=fork())==0){
//		sleep(2);							//子进程
		shmaddr=(char*)shmat(shmid,NULL,0);//系统自动选择一个地址来链接
		if(shmaddr==(void*)-1){
			printf("connect the share memory failed:%s",strerror(errno));
			return 0;
		}
		char s[20];
		intToString(getpid(),s); 
		strcpy(shmaddr,s);
		sleep(1);
		
		printf("son pid is %dn",getpid());
		printf("son get the parent's pid %sn",shmaddr);
		shmdt(shmaddr);			//断开共享内存
		exit(0);
	}
	else{

		sleep(1);
		shmctl(shmid,IPC_STAT,&buf);	//获取共享内存相关信息
		shmaddr=(char*)shmat(shmid,NULL,0);//系统自动选择一个地址连接
		if(shmaddr==(void*)-1){
			printf("connect the share memory failed:%s",strerror(errno));
			return 0; 
		}
		printf("parent pid is %dn",getpid());
		printf("parent get the son's pid %sn",shmaddr);
			
		char t[20];
		strcpy(shmaddr,t);				//将shmadr内容置'' 
		intToString(getpid(),t); 
		strcpy(shmaddr,t);
		sleep(1);
		
		shmdt(shmaddr);				//断开共享内存
		shmctl(shmid,IPC_STAT,&buf);//取得共享内存相关信息
		//当不在有任何其他相关进程使用该共享内存时系统自动销毁它
		shmctl(shmid,IPC_RMID,NULL);
	}
} 
//1.注意:sleep(1)和wait(0)对父子进程的交替操作

如图:

问题:
1.t.c:(.text+0x139):对‘sterror’未定义的引用?
2.c语言怎么将整型转化为字符串? 自定义函数:找到最大十进制,依次除并ascall码表示
3.怎么让父子进程共享同一块内存,并相互存取,读取不干涉?

心得:1.轻装出发,重载而行

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/854190.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号