sem_init
是 POSIX 线程库中用于初始化未命名信号量(unnamed semaphore)的函数,常用于多线程或多进程间的同步。以下是其概念和使用案例的详细说明:
概念
- 函数原型:
#include <semaphore.h>int sem_init(sem_t *sem, int pshared, unsigned int value);
- 参数:
sem
:指向信号量对象的指针。pshared
:决定信号量的共享范围:0
:信号量在线程间共享(同一进程内)。- 非
0
:信号量在进程间共享(需配合共享内存使用)。
value
:信号量的初始值(通常表示可用资源的数量)。
- 返回值:
- 成功返回
0
,失败返回-1
并设置errno
。
- 成功返回
使用案例
场景 1:多线程同步(线程间共享)
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>sem_t sem;
int shared_resource = 0;void* thread_func(void* arg) {sem_wait(&sem); // 等待信号量shared_resource++; // 访问共享资源printf("Thread %ld: shared_resource = %d\n", (long)pthread_self(), shared_resource);sem_post(&sem); // 释放信号量return NULL;
}int main() {pthread_t t1, t2;// 初始化信号量(线程间共享,初始值为1)if (sem_init(&sem, 0, 1) == -1) {perror("sem_init failed");return 1;}pthread_create(&t1, NULL, thread_func, NULL);pthread_create(&t2, NULL, thread_func, NULL);pthread_join(t1, NULL);pthread_join(t2, NULL);sem_destroy(&sem); // 销毁信号量return 0;
}
场景 2:多进程同步(进程间共享)
需将信号量放置在共享内存中:
#include <stdio.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <semaphore.h>int main() {// 创建共享内存int fd = shm_open("/my_shm", O_CREAT | O_RDWR, 0666);ftruncate(fd, sizeof(sem_t));sem_t *sem = mmap(NULL, sizeof(sem_t), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);// 初始化信号量(进程间共享,初始值为1)if (sem_init(sem, 1, 1) == -1) {perror("sem_init failed");return 1;}// 父子进程示例if (fork() == 0) {sem_wait(sem);printf("Child process: Accessing resource\n");sem_post(sem);_exit(0);} else {sem_wait(sem);printf("Parent process: Accessing resource\n");sem_post(sem);wait(NULL);}sem_destroy(sem); // 销毁信号量shm_unlink("/my_shm"); // 清理共享内存return 0;
}
注意事项
-
未命名 vs 命名信号量:
sem_init
用于未命名信号量,生命周期由程序控制。- 命名信号量(通过
sem_open
创建)可用于无亲缘关系的进程间同步。
-
废弃警告:
- 在较新的系统(如 Linux 2.6+),
sem_init
已被标记为废弃,建议改用sem_open
+sem_unlink
。
- 在较新的系统(如 Linux 2.6+),
-
资源释放:
- 必须调用
sem_destroy
释放信号量资源,避免内存泄漏。
- 必须调用
-
编译命令:
gcc program.c -pthread -lrt # 链接 pthread 和 rt 库(进程间共享需要)
通过合理使用 sem_init
,可以实现线程或进程间的同步控制(如互斥锁、资源计数等)。