#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
sem_t mutex;
void *my_thread() {
while (1) {
//判断信号量是否大于 0 ,如果大于 0 ,执行减一操作,并继续 sem_wait 之后的代码;如果当前 sem 等于 0 ,阻塞等待直至大于零
// (大于零之后执行减一操作,继续 sem_wait 之后的代码)
printf("测试数据 1");
sem_wait(&mutex);
//信号量值加一,直接返回;
printf("测试数据 2");
sem_post(&mutex);
printf("测试数据 3");
break;
}
return 0;
}
int main() {
pthread_t thread_1, thread_2; //声明线程 ID
// sem_open()创建一个新的 POSIX 信号量或打开一个现有的信号量。信号灯由名称标识。有关名称构造的详细信息,请参见 sem_overview(7)。
// oflag 参数指定用于控制调用操作的标志。 (可以通过包含来获得标志值的定义。)如果在 oflag 中指定 O_CREAT ,则如果信号灯尚不存在,则会创建该信号灯。
// 信号量的所有者(用户 ID)设置为调用过程的有效用户 ID 。组所有权(组 ID)设置为调用过程的有效组 ID 。如果在 oflag 中同时指定了 O_CREAT 和 O_EXCL ,
// 则如果已经存在具有给定名称的信号灯,则将返回错误。
// 如果在 oflag 中指定 O_CREAT ,则必须提供两个附加参数。mode 参数指定要放置在新信号量上的权限,就像 open(2)一样。
// (可以通过包含。获得权限位的符号定义。)权限设置针对进程 umask 进行掩码。应该向将访问信号量的每个用户类别都授予读取和写入权限。
// value 参数指定新信号量的初始值。如果指定了 O_CREAT ,并且已经存在具有给定名称的信号灯,则将忽略 mode 和 value
mutex = *sem_open("mutex", O_CREAT, S_IRWXU, 1);
// Name 用于标识信号量的名字
// Oflag 被设置为 O_CREAT 用来创建一个信号量(如果和 0_EXCL 一起,当这个信号量已经存在时候这个调用将会失败)
// mode_t 控制新的信号量的访问权限
// Value 指定信号量的初始化值
// ( 1 ) tidp:事先创建好的 pthread_t 类型的参数。成功时 tidp 指向的内存单元被设置为新创建线程的线程 ID 。
// ( 2 ) attr:用于定制各种不同的线程属性。APUE 的 12.3 节讨论了线程属性。通常直接设为 NULL 。
// ( 3 ) start_rtn:新创建线程从此函数开始运行。无参数是 arg 设为 NULL 即可。
// ( 4 ) arg:start_rtn 函数的参数。无参数时设为 NULL 即可。有参数时输入参数的地址。当多于一个参数时应当使用结构体传入。(以下举例)
//向线程函数传递参数
pthread_create(&thread_1, NULL, &my_thread, NULL);
pthread_create(&thread_2, NULL, &my_thread, NULL);
//以阻塞的方式等待 thread 指定的线程结束。当函数返回时,被等待线程的资源被收回。
// 如果线程已经结束,那么该函数会立即返回。并且 thread 指定的线程必须是 joinable 的
pthread_join(thread_1, NULL);
pthread_join(thread_2, NULL);
sem_unlink("mutex");
return 0;
}
```
报错是这个
zsh: segmentation fault ./a.out
1
ysc3839 2023-09-11 16:36:38 +08:00 via Android
调试看看吧,一般能直接定位到出问题的点。
另外如果没什么特殊需求的话(比如限制只能用 C),个人建议用 C++标准库里面的 thread mutex 等,比 POSIX API 好用。 |
2
cosiner 2023-09-11 16:48:26 +08:00
`mutex = *sem_open`, 为什么要用 * 解引用?, 那块内存你不一定有访问权限的, 还可能有其他原因, 具体我也不太懂
|
3
q8515620 2023-09-11 17:17:42 +08:00 via Android 1
segmentfalt 是访问了没有权限的内存地址,发生在 sem_wait(&mutex)这里。
mutex 是个全局变量,&mutex 是这个变量所在的内存地址,而不是你以为的信号量的地址。 你将 sem_open()返回的信号量的地址直接解引用为该地址所指向的“值”并赋值(这里应该是拷贝了一份)给了 mutex ,这样的话,你直接把信号量的地址丢弃了。 正确使用方法: sem_t *mutex; // 将 mutex 声明为指向 sem_t 的指针 mutex = sem_open("mutex", O_CREAT, S_IRWXU, 1); sem_wait(mutex); |
4
awanganddong OP 谢谢大家的解答了
|