共享内存函数封装:
1 #include <unistd.h> 2 #include <sys/types.h> 3 #include <sys/stat.h> 4 #include <fcntl.h> 5 #include <sys/mman.h> 6 #include <sys/ipc.h> 7 #include <sys/shm.h> 8 #include <sys/sem.h> 9 10 #include <stdlib.h> 11 #include <stdio.h> 12 #include <errno.h> 13 #include <string.h> 14 15 #include <sys/ipc.h> 16 #include <sys/sem.h> 17 #include "myipc_sem.h" 18 19 20 union semun { 21 int val; /* Value for SETVAL */ 22 struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */ 23 unsigned short *array; /* Array for GETALL, SETALL */ 24 struct seminfo *__buf; /* Buffer for IPC_INFO 25 (Linux specific) */ 26 }; 27 28 //@返回值 0 正确 其他错误 29 int sem_creat(int key, int *semid) 30 { 31 int ret = 0; 32 //int tmpsemid = 0; 33 34 if (semid == NULL) 35 { 36 ret = SEMERR_PARAM; 37 printf("func sem_creat() err:%d ", ret); 38 return ret; 39 } 40 ret = semget(key, 1, 0666| IPC_CREAT | IPC_EXCL); 41 if (ret == -1) 42 { 43 ret = errno; 44 //perror("semget"); 45 if (errno == EEXIST) 46 { 47 ret = SEMERR_EEXIST; 48 printf("func sem_creat() 检测到信号量集已经存在:%d ", ret); 49 return ret; 50 } 51 } 52 *semid = ret; 53 54 ret = sem_setval(*semid, 1); 55 if (ret != 0) 56 { 57 printf("func sem_setval() err:%d ", ret); 58 return ret; 59 } 60 ret = 0; 61 return ret; 62 } 63 64 int sem_open(int key, int *semid) 65 { 66 int ret = 0; 67 68 if (semid == NULL) 69 { 70 ret = SEMERR_PARAM; 71 printf("func sem_open() err:%d ", ret); 72 return ret; 73 } 74 75 ret = semget(key, 0, 0); 76 if (ret == -1) 77 { 78 ret = errno; 79 printf("func sem_open() 失败:%d ", ret); 80 return ret; 81 } 82 *semid = ret; 83 ret = 0; 84 return ret; 85 } 86 87 int sem_setval(int semid, int val) 88 { 89 int ret = 0; 90 union semun su; 91 su.val = val; 92 ret = semctl(semid, 0, SETVAL, su); 93 return ret; 94 } 95 96 /* 97 int sem_getval(int semid, int *val) 98 { 99 int ret = 0; 100 int tmpval; 101 if (val == NULL) 102 { 103 ret = SEMERR_PARAM; 104 printf("func sem_getval() err:%d ", ret); 105 return ret; 106 } 107 union semun su; 108 tmpval = su.val ; 109 ret = semctl(semid, 0, GETVAL, su); 110 *val = tmpval ; 111 printf("val:%d ", tmpval); 112 return ret; 113 } 114 */ 115 int sem_getval(int semid, int *myval) 116 { 117 int ret = 0; 118 int val; 119 union semun su; 120 val = su.val ; 121 //信号量 计数值 122 ret = semctl(semid, 0, GETVAL, su); 123 //printf("val:%d ", val); 124 125 *myval = ret; 126 ret = 0; 127 return ret; 128 } 129 130 //信号量p操作时候,需要传递好几个信息给linux内核 131 //所以linux内核定义了一个结构 132 //我要操作信号量集的下标 0 133 //我要执行什么操作 -1 +1 134 //我按照什么策略执行操作 0 UNDO NOWAITing 135 int sem_p(int semid) 136 { 137 struct sembuf buf = {0, -1, 0}; 138 int ret = 0; 139 ret = semop(semid, &buf, 1); 140 return ret; 141 } 142 143 int sem_v(int semid) 144 { 145 struct sembuf buf = {0, 1, 0}; 146 int ret = 0; 147 ret = semop(semid, &buf, 1); 148 return ret; 149 }
信号量函数封装:
1 #define _OS_LINUX_ 2 3 #if defined _OS_LINUX_ 4 #include <stdio.h> 5 #include <errno.h> 6 #include <unistd.h> 7 #include <memory.h> 8 #include <sys/ipc.h> 9 #include <sys/shm.h> 10 #include <sys/sem.h> 11 #include <sys/msg.h> 12 #include "myipc_shm.h" 13 14 #endif 15 16 int shmflag = 0; 17 int shmkey; 18 19 /*********************************************************************** 20 功能描述: 创建共享内存 21 参数说明: shmname [in] 是共享内存名,系统中唯一标志 22 shmsize [in] 是要创建的共享内存的大小; 23 shmhdl [out] 共享内存的句柄. 24 返回值: 返回0函数执行成功;非0返回错误码 25 ************************************************************************/ 26 int IPC_CreatShm(char *shmseedfile, int shmsize, int *shmhdl) 27 { 28 if(shmflag == 0) //判断接口中共享内存key是否已经存在 29 { 30 shmkey = ftok(shmseedfile, 'c'); 31 if (shmkey == -1) 32 { 33 perror("ftok"); 34 return -1; 35 } 36 37 shmflag = 1; 38 } 39 40 //创建共享内存 41 *shmhdl = shmget(shmkey,shmsize,IPC_CREAT|0666); 42 if (*shmhdl == -1) //创建失败 43 return -2; 44 return 0; 45 46 } 47 /*********************************************************************** 48 功能描述: 关联共享内存 49 参数说明: shmhdl [in] 共享的句柄 50 mapaddr [out] 共享内存首地址 51 返回值: 返回0函数执行成功;非0返回错误码 52 ************************************************************************/ 53 int 54 IPC_MapShm(int shmhdl, void **mapaddr) 55 { 56 void *tempptr = NULL; 57 58 //连接共享内存 59 tempptr = (void *)shmat(shmhdl,0,SHM_RND); 60 if ((int)tempptr == -1) //共享内存连接失败 61 return -1; 62 *mapaddr = tempptr; //导出共享内存首指针 63 64 return 0; 65 } 66 /*********************************************************************** 67 功能描述: 取消共享内存关联 68 参数说明: unmapaddr [in] 共享内存首地址 69 返回值: 返回0函数执行成功;非0返回错误码 70 ************************************************************************/ 71 int IPC_UnMapShm(void *unmapaddr) 72 { 73 int rv; 74 //取消连接共享内存 75 rv = shmdt((char *)unmapaddr); 76 if (rv == -1) //取消连接失败 77 return -1; 78 79 return 0; 80 } 81 /*********************************************************************** 82 功能描述: 删除共享内存 83 参数说明: shmhdl [in] 共享的句柄 84 返回值: 返回0函数执行成功;非0返回错误码 85 ************************************************************************/ 86 int IPC_DelShm(int shmhdl) 87 { 88 int rv; 89 //删除共享内存 90 rv = shmctl(shmhdl,IPC_RMID,NULL); 91 if(rv < 0) //删除共享内存失败 92 return -1; 93 return 0; 94 }
多进程操作共享内存:
1 #include <sys/types.h> 2 #include <unistd.h> 3 4 #include <stdlib.h> 5 #include <stdio.h> 6 #include <string.h> 7 8 #include <signal.h> 9 #include <errno.h> 10 #include <signal.h> 11 #include <sys/wait.h> 12 13 #include "myipc_sem.h" 14 #include "myipc_shm.h" 15 16 int g_key = 0x3333; 17 18 void TestFunc(int loopnum) 19 { 20 printf("loopnum:%d ", loopnum); 21 22 int ncount = 0; 23 int ret = 0; 24 int shmhdl = 0; 25 int *addr = NULL; 26 27 int semid = 0; 28 sem_open(g_key, &semid); 29 30 31 sem_p(semid); //临界区开始 32 // 33 ret = IPC_CreatShm(".", 0, &shmhdl); 34 35 ret =IPC_MapShm(shmhdl, (void **)&addr); 36 *((int *)addr) = *((int *)addr) + 1; 37 ncount = *((int *)addr); 38 printf("ncount:%d ", ncount); 39 //addr[0] = addr[0] +1; 40 ret =IPC_UnMapShm(addr); 41 sleep(2); 42 43 sem_v(semid); //临界区开始 44 // 45 printf("进程正常退出:%d ", getpid()); 46 } 47 48 int main(void ) 49 { 50 int res; 51 int procnum=10; 52 int loopnum = 100; 53 54 55 int i=0,j = 0; 56 57 printf("请输入要创建子进程的个数 : "); 58 scanf("%d", &procnum); 59 60 printf("请输入让每个子进程测试多少次 : "); 61 scanf("%d", &loopnum); 62 63 //共享内存创建 64 int ret = 0; 65 int shmhdl = 0; 66 ret = IPC_CreatShm(".", sizeof(int), &shmhdl); 67 if (ret != 0) 68 { 69 printf("func IPC_CreatShm() err:%d ", ret); 70 return ret; 71 } 72 73 74 //信号量的创建 75 int semid = 0; 76 ret = sem_creat(g_key, &semid); 77 if (ret != 0) 78 { 79 printf("func sem_creat() err:%d,重新按照open打开信号量 ", ret); 80 if (ret == SEMERR_EEXIST) 81 { 82 ret = sem_open(g_key, &semid); 83 if (ret != 0) 84 { 85 printf("按照打开的方式,重新获取sem失败:%d ", ret); 86 return ret; 87 } 88 } 89 else 90 { 91 return ret; 92 } 93 94 } 95 96 int val = 0; 97 ret = sem_getval(semid, &val); 98 if (ret != 0 ) 99 { 100 printf("func sem_getval() err:%d ", ret); 101 return ret; 102 } 103 printf("sem val:%d ", val); 104 getchar(); 105 106 pid_t pid; 107 108 for (i=0; i<procnum; i++) 109 { 110 pid = fork(); //有几个fork就有几个子进程 111 if (pid == 0) 112 { 113 for (j=0; j<loopnum; j ++) 114 { 115 TestFunc(j); 116 } 117 exit(0); 118 } 119 120 } 121 122 //让所有的子进程退出 父进程才退出 123 124 /* 125 while(1) 126 { 127 res = wait(NULL);// 128 if(res==-1) 129 { 130 if(errno==EINTR) //若阻塞中有别的信号中断 131 { 132 continue; 133 } 134 break; 135 } 136 } 137 */ 138 139 int mypid = 0; 140 while ( (mypid= waitpid(-1, NULL, WNOHANG)) > 0) 141 { 142 //printf("退出的子进程pid为:mypid:%d ", mypid); 143 ; 144 } 145 146 147 printf("父进程退出 hello... "); 148 return 0; 149 }