2026/1/10 15:56:44
网站建设
项目流程
phpcms 后台修改修改网站备案号,网站建设金手指排名信誉,网站一年的 运营费用,重庆网上办事大厅System V 信号量
概述
System V 信号量是内核提供的同步原语, 用于跨进程的互斥与资源计数。信号量本质上是一个计数器, 支持 P 操作 (wait, 减 1) 和 V 操作 (signal, 加 1)。信号量通常用于控制对共享资源的访问, 实现进程间的同步。
典型用途:
互斥锁: 初值 1, 保证同一时刻…System V 信号量概述System V 信号量是内核提供的同步原语, 用于跨进程的互斥与资源计数。信号量本质上是一个计数器, 支持 P 操作 (wait, 减 1) 和 V 操作 (signal, 加 1)。信号量通常用于控制对共享资源的访问, 实现进程间的同步。典型用途:互斥锁: 初值 1, 保证同一时刻只有一个进程进入临界区计数信号量: 初值为可用资源数, 控制并发访问额度进程间同步: 作为事件/条件的等待与通知信号量由内核维护, 通过键值 key 标识, 支持集合 (多个 sem 组成的数组)。通信原理基本概念信号量的特点:计数器: 本质上是一个非负整数计数器原子操作: P 和 V 操作是原子的, 不会被中断阻塞机制: 当信号量为 0 时, P 操作会阻塞同步原语: 用于实现互斥和同步集合概念: System V 信号量以集合形式存在实现机制创建/获取信号量集:使用semget()系统调用创建或获取信号量集通过唯一的键值 (key) 标识信号量集指定信号量集中信号量的数量返回信号量集标识符 (semid)信号量操作:使用semop()对信号量进行 P/V 操作P 操作 (wait): 信号量减 1, 如果为 0 则阻塞V 操作 (signal): 信号量加 1, 唤醒等待的进程信号量控制:使用semctl()设置信号量的初始值可以获取信号量的值可以删除信号量集同步模式:进程A: P操作等待 ──┐ ├── [信号量] ── 控制共享资源访问 进程B: P操作等待 ──┘ 进程C: V操作释放 ── 信号量1唤醒等待进程互斥模式:信号量初始值为 1进程访问共享资源前执行 P 操作访问完成后执行 V 操作保证同一时刻只有一个进程访问资源使用流程semget创建/获取信号量集 (指定 key、数量、权限, 可带 IPC_CREAT/IPC_EXCL)semctl初始化值 (SETVAL/SETALL), 可查询/删除 (GETVAL/IPC_RMID)semop执行 P/V 操作 (原子减/加), 支持阻塞或非阻塞 (SEM_UNDO/IPC_NOWAIT)使用完后可由负责的进程调用semctl(..., IPC_RMID, ...)删除信号量集API 说明semget()#includesys/sem.hintsemget(key_tkey,intnsems,intsemflg);功能: 创建或获取信号量集参数:key: 信号量集的键值 (可以用ftok()生成或使用 IPC_PRIVATE)nsems: 信号量集中信号量的数量semflg: 标志位 (IPC_CREAT, IPC_EXCL, 权限等)返回值: 成功返回信号量集标识符, 失败返回 -1常见错误: EACCES, EEXIST, ENOENT, ENOMEM, ENOSPCsemop()#includesys/sem.hintsemop(intsemid,structsembuf*sops,size_tnsops);功能: 原子执行一组 P/V 操作参数:semid: 信号量集标识符sops: 操作数组指针nsops: 操作数量返回值: 成功返回 0, 失败返回 -1常见错误: EACCES, EIDRM, EINVAL, EAGAIN (非阻塞且资源不足), EINTR (被信号中断)sembuf 结构structsembuf{unsignedshortsem_num;// 信号量索引/编号shortsem_op;// 操作值: 负数等待并减 (P), 正数加 (V), 0等待为 0shortsem_flg;// 标志位: SEM_UNDO (进程退出自动回滚), IPC_NOWAIT (非阻塞)};semctl()#includesys/sem.hintsemctl(intsemid,intsemnum,intcmd,...);功能: 控制/查询信号量参数:semid: 信号量集标识符semnum: 信号量编号cmd: 命令 (SETVAL 设置值, GETVAL 获取值, IPC_RMID 删除等)...: 可变参数 (根据 cmd 不同而不同, 需要 union semun 作为第四参数)常用 cmd:SETVAL/GETVAL: 设定/获取单个信号量值SETALL/GETALL: 设定/获取信号量数组IPC_RMID: 删除信号量集IPC_STAT/IPC_SET: 查询/设置权限与属性返回值: 根据 cmd 不同而不同, 失败返回 -1注意: 需要 union semun 作为第四参数 (用户需自行声明)示例代码示例 1: 互斥锁风格的 P/V#includestdio.h#includesys/ipc.h#includesys/sem.h#includeunistd.hunionsemun{intval;structsemid_ds*buf;unsignedshort*array;};// P 操作: 获取锁 (阻塞等待)intsem_lock(intsemid,intidx){structsembufop{.sem_numidx,.sem_op-1,.sem_flgSEM_UNDO};returnsemop(semid,op,1);}// V 操作: 释放锁intsem_unlock(intsemid,intidx){structsembufop{.sem_numidx,.sem_op1,.sem_flgSEM_UNDO};returnsemop(semid,op,1);}intmain(void){key_tkeyftok(.,s);intsemidsemget(key,1,IPC_CREAT|0666);if(semid-1){perror(semget);return1;}// 初始化为 1 (互斥锁)unionsemun arg;arg.val1;if(semctl(semid,0,SETVAL,arg)-1){perror(semctl);return1;}if(sem_lock(semid,0)-1){perror(lock);return1;}printf(PID %d in critical section\n,getpid());sleep(1);// 模拟工作sem_unlock(semid,0);// 由负责的进程删除信号量 (可选)semctl(semid,0,IPC_RMID);return0;}说明:互斥锁语义: 初值设为 1, P-1 获取, V1 释放阻塞行为: 未持有锁时 P 会睡眠; 使用 IPC_NOWAIT 可改为非阻塞SEM_UNDO: 进程异常退出时内核回滚 sem 值, 降低死锁风险示例 2: 计数信号量 (资源池)// 初始化为资源数 N; P 获取一个资源, V 归还// 将 SETVAL 初值设为可用资源总数 (例如连接数、缓冲块数)// 当 sem_op-1 时, 若值为 0 则阻塞或 EAGAIN (IPC_NOWAIT)参考examples/05-semaphore/目录下的更多示例代码。性能评价优点同步机制: 提供强大的进程同步能力原子操作: P/V 操作是原子的, 保证正确性阻塞机制: 自动处理进程阻塞和唤醒灵活性: 可以用于互斥、同步、资源计数等多种场景持久性: 信号量集在系统中持久存在缺点复杂性: API 相对复杂, 需要理解信号量概念系统限制: 系统对信号量数量有限制死锁风险: 使用不当可能导致死锁系统资源: 占用系统资源, 需要显式删除性能开销: 需要系统调用, 有一定开销性能特点延迟: 中等 (需要系统调用)吞吐量: 中等 (受系统限制影响)CPU 占用: 中等内存占用: 小 (每个信号量占用少量内存)适用场景✅ 进程同步和互斥✅ 控制共享资源访问✅ 生产者-消费者问题✅ 读者-写者问题✅ 需要复杂同步机制的场景❌ 简单的单向通信 (管道更合适)❌ 不需要同步的场景注意事项键值管理: 使用ftok()生成键值或使用 IPC_PRIVATE; key 相同会共享同一信号量集, 部署时需管理好 key 分配初始值设置: 使用semctl(SETVAL)设置信号量初始值资源清理: 使用完毕后应该删除信号量集 (semctl(IPC_RMID)); 约定哪个进程初始化/删除信号量, 避免误删死锁避免: 注意避免死锁, 合理设计 P/V 操作顺序; 保持一致的加锁顺序, 避免循环等待; 对长时间持锁的操作谨慎设计错误处理: 注意处理信号量操作失败的情况系统限制: 注意系统的信号量数量限制 (ipcs -l查看)SEM_UNDO 标志: 建议在 P/V 中使用, 防止进程崩溃后信号量泄漏, 降低死锁风险; 但大量使用可能有内核开销权限与安全: 合理设置权限位, 避免被非预期进程操作非阻塞模式: IPC_NOWAIT 可避免阻塞, 需处理 EAGAIN 重试或回退删除时机: 删除会使阻塞的 semop 返回 EIDRM; 先确保使用方已退出或能正确处理多 sem 场景:semop支持一次操作多个信号量, 可用于原子更新多个资源状态常见错误码提示EACCES: 权限不足EEXIST: IPC_CREAT|IPC_EXCL 且已存在ENOENT: 未指定 IPC_CREAT 且不存在ENOMEM/ENOSPC: 资源不足或达到系统上限EAGAIN: 非阻塞且当前不可用EIDRM: 信号量集已被删除EINTR: 被信号中断, 可按需重试EINVAL: 参数无效扩展阅读man 2 semgetman 2 semopman 2 semctlman 7 sem_overview