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

来源:互联网 发布:mac无法登录app store 编辑:程序博客网 时间:2024/05/17 21:49
/*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; }
0 0
原创粉丝点击