深入解析MSC8254多核DSP启动流程:从RCW配置到多设备I2C引导
2026/6/24 15:48:18
System V 信号量是内核提供的同步原语, 用于跨进程的互斥与资源计数。信号量本质上是一个计数器, 支持 P 操作 (wait, 减 1) 和 V 操作 (signal, 加 1)。信号量通常用于控制对共享资源的访问, 实现进程间的同步。
典型用途:
信号量由内核维护, 通过键值 key 标识, 支持集合 (多个 sem 组成的数组)。
信号量的特点:
创建/获取信号量集:
semget()系统调用创建或获取信号量集信号量操作:
semop()对信号量进行 P/V 操作信号量控制:
semctl()设置信号量的初始值同步模式:
进程A: P操作(等待) ──┐ ├──> [信号量] ──> 控制共享资源访问 进程B: P操作(等待) ──┘ 进程C: V操作(释放) ──> 信号量+1,唤醒等待进程互斥模式:
semget创建/获取信号量集 (指定 key、数量、权限, 可带 IPC_CREAT/IPC_EXCL)semctl初始化值 (SETVAL/SETALL), 可查询/删除 (GETVAL/IPC_RMID)semop执行 P/V 操作 (原子减/加), 支持阻塞或非阻塞 (SEM_UNDO/IPC_NOWAIT)semctl(..., IPC_RMID, ...)删除信号量集#include<sys/sem.h>intsemget(key_tkey,intnsems,intsemflg);key: 信号量集的键值 (可以用ftok()生成或使用 IPC_PRIVATE)nsems: 信号量集中信号量的数量semflg: 标志位 (IPC_CREAT, IPC_EXCL, 权限等)#include<sys/sem.h>intsemop(intsemid,structsembuf*sops,size_tnsops);semid: 信号量集标识符sops: 操作数组指针nsops: 操作数量structsembuf{unsignedshortsem_num;// 信号量索引/编号shortsem_op;// 操作值: 负数=等待并减 (P), 正数=加 (V), 0=等待为 0shortsem_flg;// 标志位: SEM_UNDO (进程退出自动回滚), IPC_NOWAIT (非阻塞)};#include<sys/sem.h>intsemctl(intsemid,intsemnum,intcmd,...);semid: 信号量集标识符semnum: 信号量编号cmd: 命令 (SETVAL 设置值, GETVAL 获取值, IPC_RMID 删除等)...: 可变参数 (根据 cmd 不同而不同, 需要 union semun 作为第四参数)SETVAL/GETVAL: 设定/获取单个信号量值SETALL/GETALL: 设定/获取信号量数组IPC_RMID: 删除信号量集IPC_STAT/IPC_SET: 查询/设置权限与属性#include<stdio.h>#include<sys/ipc.h>#include<sys/sem.h>#include<unistd.h>unionsemun{intval;structsemid_ds*buf;unsignedshort*array;};// P 操作: 获取锁 (阻塞等待)intsem_lock(intsemid,intidx){structsembufop={.sem_num=idx,.sem_op=-1,.sem_flg=SEM_UNDO};returnsemop(semid,&op,1);}// V 操作: 释放锁intsem_unlock(intsemid,intidx){structsembufop={.sem_num=idx,.sem_op=1,.sem_flg=SEM_UNDO};returnsemop(semid,&op,1);}intmain(void){key_tkey=ftok(".",'s');intsemid=semget(key,1,IPC_CREAT|0666);if(semid==-1){perror("semget");return1;}// 初始化为 1 (互斥锁)unionsemun arg;arg.val=1;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;}说明:
// 初始化为资源数 N; P 获取一个资源, V 归还// 将 SETVAL 初值设为可用资源总数 (例如连接数、缓冲块数)// 当 sem_op=-1 时, 若值为 0 则阻塞或 EAGAIN (IPC_NOWAIT)参考examples/05-semaphore/目录下的更多示例代码。
ftok()生成键值或使用 IPC_PRIVATE; key 相同会共享同一信号量集, 部署时需管理好 key 分配semctl(SETVAL)设置信号量初始值semctl(IPC_RMID)); 约定哪个进程初始化/删除信号量, 避免误删ipcs -l查看)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