跟着iMX28x开发套件学linux-09
九、linux应用编程之七:信号量
信号量是进程间通信的一种方式,分为有名信号量和基于共享内存的信号量(无名信号量)。这里主要用有名信号量。有名信号量的使用步骤如下:
sem_open():打开或创建一个有名信号量
sem_wait():请求信号量,当信号量>0时,信号量值减1,当信号量=0时,进程阻塞。
sem_post():释放信号量,信号量值加1
sem_close():关闭有名信号量。
sem_unlink():删除有名信号量。
函数详细说明
1) 函数原型:sem_t *sem_open(const char *name, int oflag,mode_t mode, unsigned int value);
或:sem_t *sem_open(const char *name, int oflag);//打开已有信号量可用这个
输入参数:*name,信号量名称;oflag,打开标志;mode,用户权限;value,信号量值;
返 回 值:sem_t*,信号量指针,每个指针对应一个信号量。失败返回SEM_FAILED
示 例:semid = sem_open(SEMNAME, O_CREAT, 0644, 0);或semid = sem_open(SEMNAME, 0);
2) 函数原型:int sem_wait(sem_t *sem);
输入参数:*sem,信号量指针,由sem_open()返回。
返 回 值:int,成功返回0,失败返回-1
示 例:sem_wait(semid);
3) 函数原型:int sem_post(sem_t *sem);
输入参数:*sem,信号量指针,由sem_open()返回。
返 回 值:int,成功返回0,失败返回-1
示 例:sem_post(semid);
4) 函数原型:int sem_close(sem_t *sem);
输入参数:*sem,信号量指针,由sem_open()返回。
返 回 值:int,成功返回0,失败返回-1
示 例:sem_close(semid);
5) 函数原型:int sem_unlink(const char *name);
输入参数:*name,信号量名称。
返 回 值:int,成功返回0,失败返回-1
示 例:sem_unlink(SHMNAME);
示例代码
服务端代码:
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/mman.h> #include <sys/types.h> #include <fcntl.h> #include <sys/stat.h> #include <string.h> #include <errno.h> #include <semaphore.h> #define SHMSIZE 100 #define SHMNAME "shmtest" #define SEMNAME "semtest" int main(){ int shmfd; char *ptr; sem_t *semfd; shmfd = shm_open(SHMNAME, O_RDWR|O_CREAT, 0644); if(shmfd < 0){ perror("open shm error\n"); exit(-1); } ftruncate(shmfd, SHMSIZE); ptr = mmap(NULL, SHMSIZE, PROT_READ|PROT_WRITE, MAP_SHARED, shmfd, 0); semfd = sem_open(SEMNAME, O_CREAT, 0644, 0); if(semfd == SEM_FAILED){ perror("open sem error\n"); exit(-1); } sem_wait(semfd); //wait for sem printf("server recv: %s\n", ptr); strcpy(ptr, "\0"); munmap(ptr, SHMSIZE); close(shmfd); sem_close(semfd); sem_unlink(SEMNAME); shm_unlink(SHMNAME); return 0; }
客户端代码:
#include <stdio.h> #include <stdlib.h> #include <sys/stat.h> #include <fcntl.h> #include <sys/mman.h> #include <unistd.h> #include <semaphore.h> #include <string.h> #include <errno.h> #define SHMSIZE 100 #define SHMNAME "shmtest" #define SEMNAME "semtest" int main(){ int shmfd; sem_t* semfd; char* ptr; shmfd = shm_open(SHMNAME, O_RDWR, 0); if(shmfd < 0){ perror("open shm error\n"); exit(1); } ftruncate(shmfd, SHMSIZE); ptr = mmap(NULL, SHMSIZE, PROT_READ|PROT_WRITE, MAP_SHARED, shmfd, 0); semfd = sem_open(SEMNAME, 0); if(semfd == SEM_FAILED){ perror("open sem error\n"); exit(-1); } printf("client input: "); fgets(ptr, SHMSIZE, stdin); sem_post(semfd); munmap(ptr, SHMSIZE); close(shmfd); sem_close(semfd); return 0; }
运行结果:
首先运行服务端,程序在请求信号量sem_wait()处阻塞。接着运行客户端,客户端在给共享内存ptr写入数据后,sem_post()释放信号量。服务端请求到信号量后继续运行,最后终止。
PS:需要注意的是,使用了共享内存的程序在编译链接的时候要加上-lrt和--pthread参数。