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.轻装出发,重载而行



