通过一个实例来学习进程间通信之----共享内存,以及使用信号量来保护

/*Link with -lrt or -pthread.*/#include #include #include #include #include #include #include /* For O_* constants */#include /* For mode constants */#include #define BUF_SIZE 1024//sem_t *g_prsem, *g_pwsem;int father_do_something(int shmid);int child_do_something(int shmid);int main(void){ int shmid; int pid; shmid = shmget(IPC_PRIVATE, BUF_SIZE, 0666|IPC_CREAT); if (shmid < 0) { perror("fail to shmget.\n"); return -1; } printf("main\n"); if ((pid = fork()) < 0) { perror("fail to fork.\n"); return -1; } else if (pid == 0) { child_do_something(shmid); } else { father_do_something(shmid); /*1.IPC_RMID命令实际上不从内核删除一个段,而是仅仅把这个段标记为删除,实际的删除 * 发生最后一个进程离开这个共享段时。 * 2.当cmd为IPC_RMID时,第三个参数应为NULL。呵呵,大部分我们都是这样做,用这个 * 函数删除共享内存。 */ if ((shmctl(shmid, IPC_RMID, NULL)) < 0)// { perror("fail to shmctl.\n"); return -1; } } return 0;}int child_do_something(int shmid){ /* sem_t *sem_open(const char *name,int oflag,mode_t mode,unsigned int value);*/ char *buf; sem_t *prsem, *pwsem; void *shmaddr; // printf("child_do_something\n"); prsem = sem_open("3rsem", O_CREAT, 0666, 0); if (prsem == SEM_FAILED) { perror("fail to sem_open rsem.\n"); return -1; } pwsem = sem_open("3wsem", O_CREAT, 0666, 1);//最后一个参数完成对信号量的初始化 if (pwsem == SEM_FAILED) { perror("fail to sem_open wsem.\n"); return -1; } // printf("child_do_something2222\n"); /*void *shmat(int shmid, const void *shmaddr, int shmflg);*/ /* shmaddr 为 NULL表示由于系统来完成映射指定地址 shmflg 为0 ,表示共享内存可读可写*/ shmaddr = shmat(shmid, NULL, 0);//映射共享内存 if (shmaddr == (void *)-1) { perror("fail to shmat.\n"); return -1; } buf = (char *)shmaddr; while (1) { // printf("child_do_something3333\n"); sem_wait(prsem); // printf("child_do_something4444\n"); printf("Input the string is:%s", buf);// 由于是用fgets 获取的输入,它末尾自带一 \n if ((strcmp(buf, "quit\n")) == 0) { printf("child release share memery.\n"); if ((shmdt(shmaddr)) < 0)//取消共享内存的映射 { perror("fail to shmdt.\n"); return -1; } sem_close(prsem); sem_close(pwsem); sem_unlink("3rsem"); sem_unlink("3wsem"); break; } else { sem_post(pwsem); } } return 0; }int father_do_something(int shmid){ int tmp; char *buf; void *shmaddr; sem_t *prsem, *pwsem; printf("father_do_something\n"); prsem = sem_open("3rsem", O_CREAT, 0666, 0); if (prsem == SEM_FAILED) { perror("fail to sem_open rsem.\n"); return -1; } pwsem = sem_open("3wsem", O_CREAT, 0666, 1); // sem_getvalue(g_pwsem, &tmp); // printf("father g_pwsem value1111 is:%d\n", tmp); if (pwsem == SEM_FAILED) { perror("fail to sem_open wsem.\n"); return -1; } // printf("father_do_something2222\n"); /* void *shmat(int shmid, const void *shmaddr, int shmflg); */ shmaddr = shmat(shmid, NULL, 0);//映射共享内存 if (shmaddr == (void *)-1) { perror("fail to shmat.\n"); return -1; } buf = (char *)shmaddr; while (1) { // printf("father_do_something3333\n"); sem_getvalue(pwsem, &tmp); printf("father pwsem value222 is:%d\n", tmp); if (sem_wait(pwsem) < 0) { printf("sem_wait\n"); perror("fail to sem_wait.\n"); break; } printf("Enter string\n"); fgets(buf, BUF_SIZE, stdin); buf[BUF_SIZE - 1] = '\0'; sem_post(prsem); if ((strcmp(buf, "quit\n")) == 0) { printf("father release share memery.\n"); if ((shmdt(shmaddr)) < 0)//取消映射 { perror("fail to shmdt.\n"); return -1; } sem_close(prsem); sem_close(pwsem); sem_unlink("3rsem"); sem_unlink("3wsem"); break; } } sleep(3); return 0; }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值