首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用SysV计数信号量

用SysV计数信号量
EN

Stack Overflow用户
提问于 2017-04-21 17:28:57
回答 2查看 1.1K关注 0票数 1

我试图通过一个例子来理解计数信号量的概念。但是我想在Linux中使用SysV来实现这一点。

我熟悉二进制信号量和计数信号量的理论部分。

我已经提到了这个链接

从概念上讲,信号量被用作从一个进程到另一个进程的信号机制,因此我试图编写一个简单的程序。

在下面的程序中,我希望thread_1等待,直到它没有从thread_2得到一个信号,类似地,thread_2应该等到它没有从thread_3得到一个信号。

所以输出应该如下所示:Hello From thread 3 Hello from thread 2 Hello from thread 1

我知道可以正确地使用pthread_join()来实现它,但是我想使用信号量来实现它。

代码:

代码语言:javascript
复制
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <errno.h>

int sem_id;
struct sembuf sops[3];
void thread_1(void)
{
    sops[0].sem_num = 0;
    sops[0].sem_op = 0;
    sops[0].sem_flg = 0;

    if(semop(sem_id, sops, 1) < 0)
        perror("Semop In thread 3");
    else
        printf("Hello From thread 1\n");
}
代码语言:javascript
复制
void thread_2(void)
{
    sops[0].sem_num = 0;
    sops[0].sem_op = -1;
    sops[0].sem_flg = 0;

    if(semop(sem_id, sops, 1) < 0)
        perror("Semop In thread 2");
    else
        printf("Hello from thread 2\n");
}
代码语言:javascript
复制
void thread_3(void)
{

    sops[0].sem_num = 0;
    sops[0].sem_op = -1;
    sops[0].sem_flg = 0;

    if(semop(sem_id, sops, 1) < 0)
        perror("Semop In thread 3");
    else
        printf("Hello from thread 3\n");
}
代码语言:javascript
复制
int main(void)
{
    void (*funct[]) = {thread_1, thread_2, thread_3};

    key_t semkey;
    char i;
    union semun {
               int              val;    /* Value for SETVAL */
               struct semid_ds *buf;    /* Buffer for IPC_STAT, IPC_SET */
               unsigned short  *array;  /* Array for GETALL, SETALL */
               struct seminfo  *__buf;  /* Buffer for IPC_INFO
                                           (Linux-specific) */
           }arg;
    pthread_t thread_id[3];

    semkey = ftok("/tmp", 'a');

    if(semkey < 0)
        perror("Cannot Create Semaphore Key");
    else
    {
        sem_id = semget(semkey, 1, (IPC_CREAT|IPC_EXCL|0666));
        if(sem_id < 0)
            perror("Cannot create semaphore\n");
        else
        {
            arg.val = 3;
            if (semctl(sem_id, 0, SETVAL, arg) == -1) {
                perror("semctl");
                exit(1);
             }   
        }
    }

    for(i = 0; i < 3; i++)
    {
        if(pthread_create(&thread_id[i], NULL, funct[i], NULL) < 0)
            perror("Cannot Create thread\n");
    }

   for(i = 0; i < 3; i++)
        pthread_join(thread_id[i], NULL);

    if(semctl(sem_id, 0, IPC_RMID, NULL) == -1)
        perror("semctl");

    return 0;
}

我是否必须使用多个信号量集来实现我所要做的事情?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-04-21 17:59:51

您需要两个带有计数1的互斥/信号量。假设您的线程名为t0,t1,t2,您的信号量为sem0sem1,那么t0可以自由运行并递增sem0t1等待sem0和增量sem1t2等待sem1

这里有一个完整的草案,没有错误检查:

代码语言:javascript
复制
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <errno.h>

static int sem0, sem1;
#define POST1(Sem) semop(Sem, &(struct sembuf){0,1,0}, 1)
#define WAIT1(Sem) semop(Sem, &(struct sembuf){0,-1,0}, 1)

static void* t0(void *unused) { puts("hello from t0"); POST1(sem0); return 0; }
static void* t1(void *unused) { WAIT1(sem0); puts("hello from t1"); POST1(sem1); return 0; }
static void* t2(void *unused) { WAIT1(sem1); puts("hello from t2"); return 0; }

int main(void)
{
    key_t sem0_k, sem1_k;
    sem0_k = ftok("/tmp", '0');
    sem1_k = ftok("/tmp", '1');

    sem0 = semget(sem0_k, 1, (IPC_CREAT|IPC_EXCL|0666));
    sem1 = semget(sem1_k, 1, (IPC_CREAT|IPC_EXCL|0666));

    pthread_t tids[3];
    pthread_create(tids+2, NULL, t2, NULL);
    sleep(1);
    pthread_create(tids+1, NULL, t1, NULL);
    sleep(1);
    pthread_create(tids+0, NULL, t0, NULL);

    for(int i = 0; i < 3; i++)
        pthread_join(tids[i], NULL);

    semctl(sem0, 0, IPC_RMID, NULL);
    semctl(sem1, 0, IPC_RMID, NULL);

    return 0;
}

我以反向顺序运行线程,在t0t1之间等待1秒,t1t2显示信号量,完成将线程从t0排序到t2的工作。

票数 1
EN

Stack Overflow用户

发布于 2017-04-21 18:37:00

@PSkocik,基于您的回答,我修改了我的代码,使用了一组两个信号量。以下是代码:

代码语言:javascript
复制
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <errno.h>

int sem_id;

struct sembuf sops;
void thread_1(void)
{
    /*Wait on Set1 of Semaphore*/
    sops.sem_num = 1;
    sops.sem_op = -1;
    sops.sem_flg = 0;

    if(semop(sem_id, &sops, 1) < 0)
        perror("Semop Wait In thread 3");
    else
        printf("Hello From thread 1\n");
}


void thread_2(void)
{
    /*Wait on Set0 of Semaphore*/
    sops.sem_num = 0;
    sops.sem_op = -1;
    sops.sem_flg = 0;

    if(semop(sem_id, &sops, 1) < 0)
        perror("Semop Wait In thread 2");
    else
        printf("Hello from thread 2\n");

    /*Post on Set1 of Semaphore*/        
    sops.sem_num = 1;
    sops.sem_op = 1;
    sops.sem_flg = 0;

    if(semop(sem_id, &sops, 1) < 0)
        perror("Semop Post In thread 2");
}

void thread_3(void)
{
    printf("Hello from thread 3\n");

    /*Post operation on Set0 of semaphore*/
    sops.sem_num = 0;
    sops.sem_op = 1;
    sops.sem_flg = 0;

    if(semop(sem_id, &sops, 1) < 0)
        perror("Semop In thread 3");
    else
    { ; }
}

int main(void)
{
    void (*funct[]) = {thread_1, thread_2, thread_3};

    key_t semkey;
    char i;
    union semun {
               int              val;    /* Value for SETVAL */
               struct semid_ds *buf;    /* Buffer for IPC_STAT, IPC_SET */
               unsigned short  *array;  /* Array for GETALL, SETALL */
               struct seminfo  *__buf;  /* Buffer for IPC_INFO
                                           (Linux-specific) */
           }arg;
    pthread_t thread_id[3];

    semkey = ftok("/tmp", 'a');

    if(semkey < 0)
        perror("Cannot Create Semaphore Key");
    else
    {
        sem_id = semget(semkey, 2, (IPC_CREAT|IPC_EXCL|0666));
        if(sem_id < 0)
            perror("Cannot create semaphore\n");
        else
        {
            /*arg.val = 3;
            if (semctl(sem_id, 0, SETVAL, arg) == -1) {
                perror("semctl");
                exit(1);
             }*/   
        }
    }

    for(i = 0; i < 3; i++)
    {
        if(pthread_create(&thread_id[i], NULL, funct[i], NULL) < 0)
            perror("Cannot Create thread\n");
    }

   for(i = 0; i < 3; i++)
        pthread_join(thread_id[i], NULL);

    if(semctl(sem_id, 0, IPC_RMID, NULL) == -1)
        perror("semctl");

    return 0;
}

顺便谢谢你的解释。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/43548740

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档