POSIX 命名信号量

更新时间:
2024-05-29
下载文档

POSIX 命名信号量

在前面已经介绍了 POSIX 匿名信号量的使用,POSIX 匿名信号量只能用于同一进程内的线程间通信,为了实现进程间的同步,可以使用 POSIX 命名信号量。

一个 POSIX 命名信号量必须要调用 sem_open 函数创建或打开之后才能使用。

当一个 POSIX 命名信号量使用完毕后,应该调用 sem_close 函数将其关闭;当一个 POSIX 命名信号量不再有任何用途时,应该调用 sem_unlink 函数删除它,SylixOS 会回收该信号量占用的内核资源。

命名信号量

命名信号量的创建与打开

#include <semaphore.h>
sem_t  *sem_open(const char  *name, int  flag, ...);

函数 sem_open 原型分析:

  • 此函数成功时返回一个 sem_t 类型的指针,失败时返回 NULL 并设置错误号。
  • 参数 name 是 POSIX 命名信号量的名字。
  • 参数 flag 是 POSIX 命名信号量的打开选项(O_CREAT,O_EXCL...)。
  • 参数 … 是可变参数,通常可指定打开的模式(mode 和 value)。

如果需要创建一个 POSIX 命名信号量,打开选项应该加上 O_CREAT,并且可变参数应指定 mode 和 value 的值。

如果需要打开一个已经存在的 POSIX 命名信号量,打开选项不能够包含 O_CREAT 选项标志。

命名信号量的关闭

#include <semaphore.h>
int   sem_close(sem_t  *psem);

函数 sem_close 原型分析:

  • 此函数成功返回 0,失败返回-1 并设置错误号。
  • 参数 psem 是 POSIX 命名信号量的指针。

调用 sem_close 函数将减少一次命名信号量的使用计数,但不会删除一个命名信号量,需要注意的是,如果调用 sem_close 函数企图关闭一个匿名信号量,将返回-1 并设置 errno 为 EINVAL。

命名信号量的删除

#include <semaphore.h>
int    sem_unlink(const char *name);

函数 sem_unlink 原型分析:

  • 此函数成功返回 0,失败返回-1 并设置错误号。
  • 参数 name 是 POSIX 命名信号量的名字。

sem_unlink 函数将删除一个不再使用的命名信号量,并释放系统资源。sem_unlink 函数会首先判断信号量的使用计数,如果使用计数到达了 0,则删除信号量,如果没有到达 0,则出错返回,并设置 errno 为 EBUSY。

下面程序通过命名信号量实现进程间的通信,服务器程序等待信号量 sem,当信号量解除等待后,代表命名管道中有新的数据可读,读数据完成后,服务器程序发送另一个信号量 sem1 给客户端表示读取数据完成。客户程序首先向管道中写入新的数据,然后发送信号量 sem 给服务器并等待信号量 sem1(服务器读操作完成)。

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <semaphore.h>

#define  FIFO_NAME  "/dev/fifo"
#define  SEND_STR   "server."
#define  SEM_FILE   "sem_named"
#define  SEM_FILE1  "sem_named1"

int main (int argc, char *argv[])
{
    int      fd;
    int      i;
    sem_t   *sem, *sem1;

    fd = open(FIFO_NAME, O_RDWR);
    if (fd < 0) {
        fprintf(stderr, "open fifo error.\n");
        return  (-1);
    }
    sem = sem_open(SEM_FILE, 0);
    if (sem == SEM_FAILED) {
        fprintf(stderr, "sem_open error.\n");
        return  (-1);
    }
    sem1 = sem_open(SEM_FILE, 0);
    if (sem1 == SEM_FAILED) {
        fprintf(stderr, "sem_open error.\n");
        return  (-1);
    }
    for (i = 0; i < 10; i++) {
        write(fd, SEND_STR, strlen(SEND_STR));
        fprintf(stdout, "write \"%s\" to fifo.\n", SEND_STR);
        sem_post(sem);
        sem_wait(sem1);
    }
    close(fd);
    sem_post(sem);
    sem_close(sem);
    sem_close(sem1);
    return (0);
}
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <semaphore.h>

#define  FIFO_NAME  "/dev/fifo"
#define  SEND_STR   "server."
#define  SEM_FILE   "sem_named"
#define  SEM_FILE1  "sem_named1"

int main (int argc, char *argv[])
{
    int          ret, i;
    int          fd;
    sem_t       *sem, *sem1;
    char         buf[64] = {0};

    ret = mkfifo(FIFO_NAME, 0777);
    if (ret < 0) {
        perror("mkfifo");
        fprintf(stderr, "mkfifo error.\n");
        return  (-1);
    }
    fd = open(FIFO_NAME, O_RDWR);
    if (fd < 0) {
        fprintf(stderr, "open fifo error.\n");
        return  (-1);
    }
    sem = sem_open(SEM_FILE, O_CREAT, 0644, 0);
    if (sem == SEM_FAILED) {
        fprintf(stderr, "sem_open error.\n");
        return  (-1);
    }
    sem1 = sem_open(SEM_FILE, O_CREAT, 0644, 0);
    if (sem1 == SEM_FAILED) {
        fprintf(stderr, "sem_open error.\n");
        return  (-1);
    }
    for (i = 0; i < 10; i++) {
        sem_wait(sem);
        read(fd, buf, strlen(SEND_STR));
        fprintf(stdout, "read \"%s\" from fifo.\n", buf);
        sem_post(sem1);
    }
    sem_wait(sem);
    close(fd);
    unlink(FIFO_NAME);
    sem_close(sem);
    sem_close(sem1);
    sem_unlink(SEM_FILE);
    sem_unlink(SEM_FILE1);
    return (0);
}
文档内容是否对您有所帮助?
有帮助
没帮助