V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
awanganddong
V2EX  ›  C

请教下 mac 环境下,我这几行代码的问题在哪里

  •  
  •   awanganddong · 229 天前 · 1258 次点击
    这是一个创建于 229 天前的主题,其中的信息可能已经有所发展或是发生改变。
        
    #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
    4 条回复    2023-09-12 22:49:02 +08:00
    ysc3839
        1
    ysc3839  
       229 天前 via Android
    调试看看吧,一般能直接定位到出问题的点。

    另外如果没什么特殊需求的话(比如限制只能用 C),个人建议用 C++标准库里面的 thread mutex 等,比 POSIX API 好用。
    cosiner
        2
    cosiner  
       229 天前
    `mutex = *sem_open`, 为什么要用 * 解引用?, 那块内存你不一定有访问权限的, 还可能有其他原因, 具体我也不太懂
    q8515620
        3
    q8515620  
       229 天前 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);
    awanganddong
        4
    awanganddong  
    OP
       228 天前
    谢谢大家的解答了
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   897 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 22:06 · PVG 06:06 · LAX 15:06 · JFK 18:06
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.