跟着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参数。

posted on 2018-11-16 23:20  diskiii  阅读(297)  评论(0编辑  收藏  举报

导航