Linux IPC 同步(四):信号量

Posix  semaphore

有名信号量

/* sem_open - initialize and open a named semaphore */
#include <fcntl.h>           /* For O_* constants */
#include <sys/stat.h>        /* For mode constants */
#include <semaphore.h>
sem_t *sem_open(const char *name, int oflag);
sem_t *sem_open(const char *name, int oflag, mode_t mode, unsigned int value);

/* sem_wait, sem_timedwait, sem_trywait - lock a semaphore */
#include <semaphore.h>
int sem_wait(sem_t *sem);
int sem_trywait(sem_t *sem);
int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout);

/* sem_post - unlock a semaphore */
#include <semaphore.h>
int sem_post(sem_t *sem);

/* sem_close - close a named semaphore */
#include <semaphore.h>
int sem_close(sem_t *sem);

/* sem_unlink - remove a named semaphore */
#include <semaphore.h>
int sem_unlink(const char *name);

Link with -pthread.

基于内存的信号量

/* sem_init - initialize an unnamed semaphore */
#include <semaphore.h>
int sem_init(sem_t *sem, int pshared, unsigned int value);

/* sem_destroy - destroy an unnamed semaphore */
#include <semaphore.h>
int sem_destroy(sem_t *sem);

sem_init() initializes the unnamed semaphore at the address pointed to by sem. The value argument specifies the initial value for the semaphore.

The pshared argument indicates whether this semaphore is to be shared between the threads of a process, or between processes.

If pshared has the value 0, then the semaphore is shared between the threads of a process, and should be located at some address that is visible

to all threads (e.g., a global variable, or a variable allocated dynamically on the heap).

如果某个基于内存的信号量是在不同进程间共享的(sem_init的pshared参数为1),那么该信号量必须存放在共享内存中。

Posix共享内存和System V共享内存都是随内核持续的,因此只要共享内存存在,共享内存上的信号量也存在着。

信号量, 互斥锁和条件变量三者之间的差异:

(1) 信号量还有一个互斥锁没有提供的特性:互斥锁必须总是由锁住它的线程解锁,信号量的post动作却不必由执行它的wait操作的同一线程执行.

(2) 互斥锁要么被锁主,要么被解开(类似二值信号量)

(3) 信号量有一个与之关联的状态, 信号量的post动作总是被记住. 而向一个条件变量发送信号时, 如果没有线程等待在该条件变量上, 那么发出的信号将会丢失.

POSIX信号量的限制

SEM_NSEMS_MAX  一个进程可以同时打开着的最大信号量数目

SEM_VALUE_MAX  一个信号量的最大值

System V信号量

System V 创建和操作都是信号量集合

/* semget - get a System V semaphore set identifier */
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
int semget(key_t key, int nsems, int semflg);

/* semop, semtimedop - System V semaphore operations */
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
int semop(int semid, struct sembuf *sops, unsigned nsops);
int semtimedop(int semid, struct sembuf *sops, unsigned nsops, struct timespec *timeout);

/* semctl - System V semaphore control operations */
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
int semctl(int semid, int semnum, int cmd, ...);

union semun {
     int              val;    /* Value for SETVAL */
     struct semid_ds *buf;    /* Buffer for IPC_STAT, IPC_SET */
     unsigned short  *array;  /* Array for GETALL, SETALL */
     struct seminfo  *__buf;  /* Buffer for IPC_INFO  (Linux-specific) */
};

/* The semid_ds data structure is defined in <sys/sem.h> as follows: */
struct semid_ds {
     struct ipc_perm sem_perm;  /* Ownership and permissions */
     time_t          sem_otime; /* Last semop time */
     time_t          sem_ctime; /* Last change time */
     unsigned long   sem_nsems; /* No. of semaphores in set */
};

/* The ipc_perm structure is defined as follows (the highlighted fields are settable using IPC_SET): */
struct ipc_perm {
     key_t          __key; /* Key supplied to semget(2) */
     uid_t          uid;   /* Effective UID of owner */
     gid_t          gid;   /* Effective GID of owner */
     uid_t          cuid;  /* Effective UID of creator */
     gid_t          cgid;  /* Effective GID of creator */
     unsigned short mode;  /* Permissions */
     unsigned short __seq; /* Sequence number */
};

注: 1. semget如果只是访问一个信号量集合,那么nsems参数指定为0。一旦创建好了一个信号量集合,其中的信号量数目不可改变。

2. semget的flag参数可以是SEM_R(R代表Read),SEM_A(A代表Alter),也可以按位或上 IPC_CREAT、IPC_EXCL

3. semop中的struct sembuf

Each semaphore in a System V semaphore set has the following associated values:

unsigned short semval;      /*  semaphore value */
             unsigned short semzcnt;    /* # waiting for zero */
             unsigned short semncnt;    /* # waiting for increase */
             pid_t sempid;           /* ID of process that did last op */

semop() performs operations on selected semaphores in the set indicated by semid. Each of the nsops elements in the array pointed to by sops
             specifies an operation to be performed on a single semaphore. The elements of this structure are of type struct sembuf, containing the following
             members:

unsigned short sem_num;    /* semaphore number */
             short sem_op;            /* semaphore operation */
             short sem_flg;            /* operation flags */

 System V 信号量的限制

时间: 2024-08-29 07:57:13

Linux IPC 同步(四):信号量的相关文章

细说linux IPC(四):posix 共享内存

上一节讲了由open函数打开一个内存映射文件,再由mmap函数把得到的描述符映射到当前进程地址空间中来.这一节说说另外一种类似的共享内存方法,即 有shm_open函数打开一个Posix.1 IPC名字(也许是文件系统中的一个路径名),所返回的描述符由函数mmap映射到当前进程地址空间.        posix共享内存和尚上一节类似,首先需要制定一个名字参数调用shm_open ,以创建一个新的共享内存对象或打开一个已存在的共享内存对象:然后再调用mmap把共享内存区映射到调用进程的地址空间中

linux内核同步之信号量、顺序锁、RCU、完成量、关闭中断【转】

转自:http://blog.csdn.net/goodluckwhh/article/details/9006065 版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[-] 一信号量 信号量的概念 信号量的数据结构和相关API 数据结构 初始化 获取和释放信号量 读写信号量的概念 读写信号量的数据结构 二顺序锁 顺序锁的概念 数据结构 写操作 读操作 三Read-Copy Update RCU 写操作 读操作 释放旧的版本 四完成量Completions 完成量的概念 数据结构

Linux IPC 同步(三):记录锁

进程间的互斥,我们可以让这些进程共享某个内存区(mmap实现),然后在该共享内存区中使用某种类型的同步变量 但是,fcntl记录上锁往往更容易使用. #include <unistd.h> #include <fcntl.h> int fcntl(int fd, int cmd, ... /* struct flock *arg */ ); struct flock { ... short l_type; /* Type of lock: F_RDLCK, F_WRLCK, F_U

Linux IPC 同步(二):读写锁

读写锁的分配规则如下: 1.  只要没有线程持有某个指定的读写锁用于写,那么任意数目的线程可以持有该读写锁用于读: 2.  仅当没有线程持有某个指定的读写锁用于读或者用于写,才能分配读写锁用于写. 这样的访问方式也称为共享-独占上锁(shared-exclusion) 那么我想到了这样一个场景: 线程A要写数据,上锁未果被阻塞,期间不断有读者来读,线程A饿死......  (实验验证之) int pthread_rwlock_init(pthread_rwlock_t *, pthread_rw

细说linux IPC(三):mmap系统调用共享内存

前面讲到socket的进程间通信方式,这种方式在进程间传递数据时首先需要从进程1地址空间中把数据拷贝到内核,内核再将数据拷贝到进程2的地址空间 中,也就是数据传递需要经过内核传递.这样在处理较多数据时效率不是很高,而让多个进程共享一片内存区则解决了之前socket进程通信的问题.共享内存 是最快的进程间通信 ,将一片内存映射到多个进程地址空间中,那么进程间的数据传递将不在涉及内核.        共享内存并不是从某一进程拥有的内存中划分出来的:进程的内存总是私有的.共享内存是从系统的空闲内存池中

Linux环境编程之同步(四):Posix信号量

信号量是一种用于提供不同进程间或一个给定进程的不同线程间同步手段的原语.有三种类型:Posix有名信号量,使用Posix IPC名字标识:Posix基于内存的信号量,存放在共享内存区中:System V信号量,在内核中维护.这三种信号量都可用于进程间或线程间的同步. 图1 由两个进程使用的一个二值信号量 图2 由两个进程使用的一个Posix有名二值信号量 图3 由一个进程内的两个线程共享的基于内存的信号量 一个进程可以在某个信号量上执行的三种操作: 1.创建一个信号量,这要求调用者指定初始值,对

Linux环境编程之IPC进程间通信(四):管道和FIFO比较

系统加于管道和FIFO的唯一限制是: 1.OPEN_MAX 一个进程在任意时刻打开的最大描述符数.可以通过调用sysconf函数查询. 2.PIPE_BUF 可原子地写往一个管道或FIFO的最大数据量.Posix任务它是一个路径名变量,它的值可以随指定的路径名而变化,因为不同的路径名可以落在不同文件系统上,而这些文件系统可能有不同的特征.所以PIPE_BUF可通过pathconf函数取得. pipeconf.c #include <stdio.h> #include <stdlib.h&

使用信号量控制Linux线程同步

线程同步 在现实生活中,有些东西就必须是按顺序执行的,只有我完成了以后,你才能在我的劳动成果上接着干:不能我还没有完成,你就开始干活了.这就是线程同步最直白的解释了. 在进行程序设计时,亦是如此.线程同步,同步的是什么?它同步的是对共享资源(内存区域,公共变量等)或者临界区域的访问.有的时候,这些共享 资源和临界区域,就只能容忍一个线程对它进行操作(读或者写,读操作一般不控制,主要是写操作),这个时候,我们必须要对这些共享资源或者临界区域进行同 步,那么如何对它们进行线程同步呢? 在Linux中

Linux IPC 之信号量

信号量(也叫信号灯)是一种用于提供不同进程间或一个给定进程的不同线程间同步手段的原语. 信号量是进程/线程同步的一种方式,有时候我们需要保护一段代码,使它每次只能被一个执行进程/线程运行,这种工作就需要一个二进制开关: 有时候需要限制一段代码可以被多少个进程/线程执行,这就需要用到关于计数信号量.信号量开关是二进制信号量的一种逻辑扩展,两者实际调用的函数都是一样. 信号量分为以下三种. 1.System V信号量,在内核中维护,可用于进程或线程间的同步,常用于进程的同步. 2.Posix有名信号