来自C,Linux中不同进程的线程同步

时间:2019-05-11 06:03:40

标签: c linux multithreading multiprocessing semaphore

我有一个要求,首先我必须制作以下过程树: here

我已成功完成此操作,但此后,我还必须在进程P8中创建5个线程(在另一个任务中必须以给定的方式进行同步),并在进程P4中创建6个线程。这时的主要任务是以这种方式同步来自P8和P4的某些线程:来自P4的线程1必须在来自P8的线程1之前结束,但是来自P4的线程4只能在来自P8的线程1结束之后开始(开始/结束)线程意味着我必须打印一条消息)。我尝试执行以下操作,这对我来说很有意义: 这是主程序:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include "a2_helper.h"

int thread_numbers[35];
int started = 0;
int finished = 0;
int barr_count = 0;

sem_t *msem;
sem_t *sem_aux;
sem_t *sem_thd;
sem_t *sem_one;
sem_t *sem_two;

typedef struct thd_s
{
    int id;
    pthread_t thd;
    pthread_mutex_t *lock;
    pthread_cond_t *cond;
    int process_nr;
}THD;

void *thread_function_diff(void *args)
{
    THD *thd = (THD *)args;

    if (thd->process_nr == 8 && thd->id == 1)
    {
        info(BEGIN, thd->process_nr, thd->id);
        sem_wait(sem_one);
        info(END, thd->process_nr, thd->id);
        sem_post(sem_two);
    }
    else if (thd->process_nr == 4 && thd->id == 1)
    {
        info(BEGIN, thd->process_nr, thd->id);
        info(END, thd->process_nr, thd->id);
        sem_post(sem_one);
    }
    else if (thd->process_nr == 4 && thd->id == 4)
    {
        sem_wait(sem_two);
        info(BEGIN, thd->process_nr, thd->id);
        info(END, thd->process_nr, thd->id);
    }
    else
    {
        info(BEGIN, thd->process_nr, thd->id);
        info(END, thd->process_nr, thd->id);
    }

    pthread_exit(0);
}

void *thread_function_barr(void *args)
{
    THD *thd = (THD *)args;

    sem_wait(msem);
//
//    if (thd->id == 31 || thd->id == 32 || thd->id == 33 || thd->id == 34)
//    {
//        info(BEGIN, thd->process_nr, thd->id);
//        sem_post(sem_thd);
//        sem_wait(sem_aux);
//        info(END, thd->process_nr, thd->id);
//    }
//    else
//    {
//        if (thd->id == 13)
//        {
//            sem_wait(sem_thd);
//            sem_wait(sem_thd);
//            sem_wait(sem_thd);
//            sem_wait(sem_thd);
//            info(BEGIN, thd->process_nr, thd->id);
//            info(END, thd->process_nr, thd->id);
//            sem_post(sem_aux);
//            sem_post(sem_aux);
//            sem_post(sem_aux);
//            sem_post(sem_aux);
//        }
//        else
//        {
            info(BEGIN, thd->process_nr, thd->id);
            info(END, thd->process_nr, thd->id);
//        }
//    }

    sem_post(msem);

    pthread_exit(0);
}

void *thread_function(void *args)
{
    THD *thd = (THD *)args;

    pthread_mutex_lock(thd->lock);
    while (started == 0 && thd->id == 3)
    {
        pthread_cond_wait(thd->cond, thd->lock);
    }
    info(BEGIN, thd->process_nr, thd->id);
    pthread_mutex_unlock(thd->lock);

    info(END, thd->process_nr, thd->id);
    pthread_mutex_lock(thd->lock);
    if (thd->id == 3)
    {
        finished = 1;
        pthread_cond_signal(thd->cond);
    }
    pthread_mutex_unlock(thd->lock);

    pthread_exit(0);
}

void *thread_function5(void *args)
{
    THD *thd = (THD *)args;

    started = 1;
    info(BEGIN, thd->process_nr, thd->id);
    pthread_cond_signal(thd->cond);

    pthread_mutex_lock(thd->lock);
    while (finished == 0)
    {
        pthread_cond_wait(thd->cond, thd->lock);
    }
    info(END, thd->process_nr, thd->id);
    pthread_mutex_unlock(thd->lock);

    pthread_exit(0);
}

int main()
{
    init();
    info(BEGIN, 1, 0);

    sem_one = sem_open("sem_one", O_CREAT, 0644, 0);
    sem_two = sem_open("sem_two", O_CREAT, 0644, 0);

    pid_t pid2 = -1, pid3 = -1, pid8 = -1;

    pid8 = fork();
    if (pid8 == 0)
    {
        info(BEGIN, 8, 0);

        THD thds[5];
        pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
        pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

        for (int i = 4; i >= 0; i--)
        {
            thds[i].id = i + 1;
            thds[i].process_nr = 8;
            thds[i].lock = &lock;
            thds[i].cond = &cond;

            if (thds[i].id == 5)
            {
                pthread_create(&(thds[i].thd), NULL, thread_function5, &thds[i]);
            }
            else if (thds[i].id == 1)
            {
                pthread_create(&(thds[i].thd), NULL, thread_function_diff, &thds[i]);
            }
            else
            {
                pthread_create(&(thds[i].thd), NULL, thread_function, &thds[i]);
            }
        }

        for (int i = 4; i >= 0; i--)
        {
            pthread_join(thds[i].thd, NULL);
        }

        pthread_cond_destroy(&cond);
        pthread_mutex_destroy(&lock);

        info(END, 8, 0);
        exit(0);
    }
    else
    {
        wait(NULL);
    }

    pid2 = fork();
    if (pid2 == 0)
    {
        info(BEGIN, 2, 0);

        pid_t pid4 = -1, pid5 = -1, pid9 = -1;

        pid4 = fork();
        if (pid4 == 0)
        {
            info(BEGIN, 4, 0);

            THD thds[6];

            for (int i = 5; i >= 0; i--)
            {
                thds[i].id = i + 1;
                thds[i].process_nr = 4;
                thds[i].lock = NULL;
                thds[i].cond = NULL;
                pthread_create(&(thds[i].thd), NULL, thread_function_diff, &thds[i]);
            }

            for (int i = 5; i >= 0; i--)
            {
                pthread_join(thds[i].thd, NULL);
            }

            info(END, 4, 0);
            exit(0);
        }
        else
        {
            wait(NULL);
        }

        pid5 = fork();
        if (pid5 == 0)
        {
            info(BEGIN, 5, 0);

            THD thds[36];
            sem_unlink("thdsemaphore");
            sem_unlink("auxsemaphore");
            sem_unlink("barriersemaphore");

            msem = sem_open("barriersemaphore", O_CREAT, 0644, 5);
            sem_aux = sem_open("auxsemaphore", O_CREAT, 0644, 0);
            sem_thd = sem_open("thdsemaphore", O_CREAT, 0644, 0);
            pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;

            for (int i = 35; i >= 0; i--)
            {
                if (i + 1 == 13)
                {
                    thread_numbers[i] = 36;
                }
                else
                {
                    thread_numbers[i] = i + 1;
                }

                thds[i].id = i + 1;
                thds[i].process_nr = 5;
                thds[i].lock = &lock;
                thds[i].cond = NULL;
                pthread_create(&(thds[i].thd), NULL, thread_function_barr, &thds[i]);
            }

            for (int i = 35; i >= 0; i--)
            {
                pthread_join(thds[i].thd, NULL);
            }

            pid_t pid6 = -1;
            pid6 = fork();
            if (pid6 == 0)
            {
                info(BEGIN, 6, 0);
                info(END, 6, 0);
                exit(0);
            }
            else
            {
                wait(NULL);
            }

            pthread_mutex_destroy(&lock);

            sem_close(sem_thd);
            sem_unlink("thdsemaphore");
            sem_close(sem_aux);
            sem_unlink("auxsemaphore");
            sem_close(msem);
            sem_unlink("barriersemaphore");

            info(END, 5, 0);
            exit(0);
        }
        else
        {
            wait(NULL);
        }

        pid9 = fork();
        if (pid9 == 0)
        {
            info(BEGIN, 9, 0);

            info(END, 9, 0);
            exit(0);
        }
        else
        {
            wait(NULL);
        }

        info(END, 2, 0);
        exit(0);
    }
    else
    {
        wait(NULL);
    }

    pid3 = fork();
    if (pid3 == 0)
    {
        info(BEGIN, 3, 0);

        pid_t pid7 = -1;

        pid7 = fork();
        if (pid7 == 0)
        {
            info(BEGIN, 7, 0);

            info(END, 7, 0);
            exit(0);
        }
        else
        {
            wait(NULL);
        }

        info(END, 3, 0);
        exit(0);
    }
    else
    {
        wait(NULL);
    }

    sem_close(sem_one);
    sem_close(sem_two);
    sem_unlink("sem_one");
    sem_unlink("sem_two");

    info(END, 1, 0);
    return 0;
}

问题是,如果我这样尝试,来自P8的线程1将无休止地等待获得对信号量的许可,但是该渗透是由来自P4的线程1给出的,它永远都没有机会运行,因为主要功能,我必须确保任何进程的主线程都不应在其他线程之前结束,并且所有进程都应等待其子进程结束。

这是a2_helper.h:

#ifndef __A2_HELPER_H__
#define __A2_HELPER_H__

#define BEGIN 1
#define END 2

void init();
int info(int action, int processNr, int threadNr);

#endif

这是a2_helper.c:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h> 
#include <sys/socket.h>
#include <netinet/in.h>
#include <semaphore.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>
#include <sys/prctl.h>
#include <signal.h>

#include "a2_helper.h"

#define SEM_NAME "A2_HELPER_SEM_17871"
#define SERVER_PORT 1988

#define XSTR(s) STR(s)
#define STR(s) #s
#define CHECK(c) if(!(c)){perror("info function failed at line " XSTR(__LINE__)); break;}

int initialized = 0;

int info(int action, int processNr, int threadNr){
    int msg[6];
    int sleepTime = 0;
    int sockfd = -1;
    struct sockaddr_in serv_addr;
    sem_t *sem = SEM_FAILED;
    int err = -1;

    if(initialized == 0){
        printf("init() function not called\n");
        return -1;
    }
    do{
        CHECK((sem = sem_open(SEM_NAME, 0)) != SEM_FAILED);

        //prepare the message
        msg[0] = action;
        msg[1] = processNr;
        msg[2] = threadNr;
        msg[3] = getpid();
        msg[4] = getppid();
        msg[5] = pthread_self();

        CHECK((sockfd = socket(AF_INET, SOCK_STREAM, 0)) >= 0);

        memset(&serv_addr, 0, sizeof(serv_addr));
        serv_addr.sin_family = AF_INET;
        serv_addr.sin_port = htons(SERVER_PORT);

        CHECK(sem_wait(sem) == 0);
        err = -2;
        if(connect(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) >= 0){
            CHECK(write(sockfd, msg, sizeof(msg)) == sizeof(msg));
            CHECK(read(sockfd, &sleepTime, sizeof(sleepTime)) == sizeof(sleepTime));
            printf("[T] ");
        }else{
            printf("[ ] ");
        }
        printf("%s P%d T%d pid=%d ppid=%d tid=%d\n", msg[0]==BEGIN?"BEGIN":" END ", msg[1], msg[2], msg[3], msg[4], msg[5]);
        CHECK(sem_post(sem) == 0);
        err = -1;
        usleep(sleepTime);
        err = 0;
    }while(0);
    if(sockfd >= 0){
        close(sockfd);
    }
    if(err==-2){
        sem_post(sem);
    }
    return err;
}

void atfork_prepare(){
    sem_t *sem = SEM_FAILED;
    do{
        CHECK((sem = sem_open(SEM_NAME, O_CREAT, 0644, 1)) != SEM_FAILED);
        CHECK(sem_wait(sem) == 0);
    }while(0);
}

void atfork_parent(){
    sem_t *sem = SEM_FAILED;
    do{
        CHECK((sem = sem_open(SEM_NAME, O_CREAT, 0644, 1)) != SEM_FAILED);
        CHECK(sem_post(sem) == 0);
    }while(0);
}

void atfork_child(){
    prctl(PR_SET_PDEATHSIG, SIGHUP);
}

void init(){
    sem_t *sem = SEM_FAILED;
    if(initialized != 0){
        printf("init() function already called\n");
        return;
    }
    do{
        pthread_atfork(atfork_prepare, atfork_parent, atfork_child);
        sem_unlink(SEM_NAME);
        CHECK((sem = sem_open(SEM_NAME, O_CREAT, 0644, 1)) != SEM_FAILED);
        initialized = 1;
    }while(0);
}

a2_helper.c和a2_helper.h已经实现,我只需要使用它们即可。

1 个答案:

答案 0 :(得分:1)

我认为问题出在您的wait()。主叉pid8,然后等待其完成,然后再移至叉pid2(后者又叉pid4)。在pid8完成之前,Pid2无法运行;因此它们的线程无法协调。

您应该(从主要人员)开除所有三个叉子,而不是在每次叉子之后等待, 然后等待三遍。在pid2中,您应该执行相同的操作。

我不确定预期的输出是什么,但是当我更改它时,它从打印11行并挂起生成该行并退出:

[ ] BEGIN P1 T0 pid=17861 ppid=17097 tid=1351051072
[ ] BEGIN P2 T0 pid=17863 ppid=17861 tid=1351051072
[ ] BEGIN P8 T0 pid=17862 ppid=17861 tid=1351051072
[ ] BEGIN P3 T0 pid=17864 ppid=17861 tid=1351051072
[ ] BEGIN P8 T1 pid=17862 ppid=17861 tid=1308952320
[ ] BEGIN P8 T5 pid=17862 ppid=17861 tid=1342523136
[ ] BEGIN P8 T4 pid=17862 ppid=17861 tid=1334130432
[ ] BEGIN P4 T0 pid=17867 ppid=17863 tid=1351051072
[ ] BEGIN P4 T6 pid=17867 ppid=17863 tid=1342523136
[ ] BEGIN P7 T0 pid=17871 ppid=17864 tid=1351051072
[ ] BEGIN P8 T2 pid=17862 ppid=17861 tid=1317345024
[ ] BEGIN P4 T3 pid=17867 ppid=17863 tid=1317345024
[ ] BEGIN P9 T0 pid=17879 ppid=17863 tid=1351051072
[ ] BEGIN P4 T5 pid=17867 ppid=17863 tid=1334130432
[ ] BEGIN P4 T1 pid=17867 ppid=17863 tid=1300559616
[ ]  END  P4 T5 pid=17867 ppid=17863 tid=1334130432
[ ]  END  P4 T6 pid=17867 ppid=17863 tid=1342523136
[ ] BEGIN P4 T2 pid=17867 ppid=17863 tid=1308952320
[ ]  END  P7 T0 pid=17871 ppid=17864 tid=1351051072
[ ]  END  P8 T2 pid=17862 ppid=17861 tid=1317345024
[ ] BEGIN P8 T3 pid=17862 ppid=17861 tid=1325737728
[ ] BEGIN P5 T0 pid=17873 ppid=17863 tid=1351051072
[ ]  END  P4 T3 pid=17867 ppid=17863 tid=1317345024
[ ]  END  P9 T0 pid=17879 ppid=17863 tid=1351051072
[ ]  END  P4 T1 pid=17867 ppid=17863 tid=1300559616
[ ]  END  P8 T1 pid=17862 ppid=17861 tid=1308952320
[ ]  END  P4 T2 pid=17867 ppid=17863 tid=1308952320
[ ]  END  P8 T3 pid=17862 ppid=17861 tid=1325737728
[ ]  END  P3 T0 pid=17864 ppid=17861 tid=1351051072
[ ] BEGIN P5 T34 pid=17873 ppid=17863 tid=1325737728
[ ] BEGIN P5 T33 pid=17873 ppid=17863 tid=1317345024
[ ] BEGIN P5 T31 pid=17873 ppid=17863 tid=1300559616
[ ] BEGIN P4 T4 pid=17867 ppid=17863 tid=1325737728
[ ] BEGIN P5 T36 pid=17873 ppid=17863 tid=1342523136
[ ] BEGIN P5 T30 pid=17873 ppid=17863 tid=1292166912
[ ]  END  P5 T33 pid=17873 ppid=17863 tid=1317345024
[ ]  END  P5 T30 pid=17873 ppid=17863 tid=1292166912
[ ] BEGIN P5 T35 pid=17873 ppid=17863 tid=1334130432
[ ] BEGIN P5 T2 pid=17873 ppid=17863 tid=1057171200
[ ]  END  P5 T36 pid=17873 ppid=17863 tid=1342523136
[ ]  END  P5 T34 pid=17873 ppid=17863 tid=1325737728
[ ]  END  P8 T5 pid=17862 ppid=17861 tid=1342523136
[ ]  END  P8 T4 pid=17862 ppid=17861 tid=1334130432
[ ]  END  P4 T4 pid=17867 ppid=17863 tid=1325737728
[ ]  END  P5 T31 pid=17873 ppid=17863 tid=1300559616
[ ]  END  P5 T35 pid=17873 ppid=17863 tid=1334130432
[ ]  END  P4 T0 pid=17867 ppid=17863 tid=1351051072
[ ] BEGIN P5 T26 pid=17873 ppid=17863 tid=1258596096
[ ] BEGIN P5 T28 pid=17873 ppid=17863 tid=1275381504
[ ] BEGIN P5 T29 pid=17873 ppid=17863 tid=1283774208
[ ]  END  P5 T28 pid=17873 ppid=17863 tid=1275381504
[ ]  END  P5 T2 pid=17873 ppid=17863 tid=1057171200
[ ]  END  P8 T0 pid=17862 ppid=17861 tid=1351051072
[ ]  END  P5 T26 pid=17873 ppid=17863 tid=1258596096
[ ] BEGIN P5 T27 pid=17873 ppid=17863 tid=1266988800
[ ]  END  P5 T29 pid=17873 ppid=17863 tid=1283774208
[ ] BEGIN P5 T25 pid=17873 ppid=17863 tid=1250203392
[ ] BEGIN P5 T24 pid=17873 ppid=17863 tid=1241810688
[ ]  END  P5 T27 pid=17873 ppid=17863 tid=1266988800
[ ]  END  P5 T25 pid=17873 ppid=17863 tid=1250203392
[ ] BEGIN P5 T23 pid=17873 ppid=17863 tid=1233417984
[ ]  END  P5 T24 pid=17873 ppid=17863 tid=1241810688
[ ] BEGIN P5 T22 pid=17873 ppid=17863 tid=1225025280
[ ] BEGIN P5 T17 pid=17873 ppid=17863 tid=1183061760
[ ]  END  P5 T22 pid=17873 ppid=17863 tid=1225025280
[ ]  END  P5 T23 pid=17873 ppid=17863 tid=1233417984
[ ] BEGIN P5 T14 pid=17873 ppid=17863 tid=1157883648
[ ]  END  P5 T17 pid=17873 ppid=17863 tid=1183061760
[ ] BEGIN P5 T18 pid=17873 ppid=17863 tid=1191454464
[ ] BEGIN P5 T13 pid=17873 ppid=17863 tid=1149490944
[ ] BEGIN P5 T15 pid=17873 ppid=17863 tid=1166276352
[ ]  END  P5 T14 pid=17873 ppid=17863 tid=1157883648
[ ]  END  P5 T18 pid=17873 ppid=17863 tid=1191454464
[ ] BEGIN P5 T11 pid=17873 ppid=17863 tid=1132705536
[ ]  END  P5 T13 pid=17873 ppid=17863 tid=1149490944
[ ]  END  P5 T15 pid=17873 ppid=17863 tid=1166276352
[ ] BEGIN P5 T10 pid=17873 ppid=17863 tid=1124312832
[ ] BEGIN P5 T5 pid=17873 ppid=17863 tid=1082349312
[ ]  END  P5 T11 pid=17873 ppid=17863 tid=1132705536
[ ] BEGIN P5 T7 pid=17873 ppid=17863 tid=1099134720
[ ] BEGIN P5 T4 pid=17873 ppid=17863 tid=1073956608
[ ]  END  P5 T5 pid=17873 ppid=17863 tid=1082349312
[ ]  END  P5 T7 pid=17873 ppid=17863 tid=1099134720
[ ]  END  P5 T4 pid=17873 ppid=17863 tid=1073956608
[ ]  END  P5 T10 pid=17873 ppid=17863 tid=1124312832
[ ] BEGIN P5 T6 pid=17873 ppid=17863 tid=1090742016
[ ] BEGIN P5 T3 pid=17873 ppid=17863 tid=1065563904
[ ] BEGIN P5 T8 pid=17873 ppid=17863 tid=1107527424
[ ] BEGIN P5 T9 pid=17873 ppid=17863 tid=1115920128
[ ] BEGIN P5 T12 pid=17873 ppid=17863 tid=1141098240
[ ]  END  P5 T6 pid=17873 ppid=17863 tid=1090742016
[ ]  END  P5 T12 pid=17873 ppid=17863 tid=1141098240
[ ]  END  P5 T8 pid=17873 ppid=17863 tid=1107527424
[ ]  END  P5 T9 pid=17873 ppid=17863 tid=1115920128
[ ] BEGIN P5 T20 pid=17873 ppid=17863 tid=1208239872
[ ] BEGIN P5 T21 pid=17873 ppid=17863 tid=1216632576
[ ] BEGIN P5 T19 pid=17873 ppid=17863 tid=1199847168
[ ] BEGIN P5 T16 pid=17873 ppid=17863 tid=1174669056
[ ]  END  P5 T3 pid=17873 ppid=17863 tid=1065563904
[ ]  END  P5 T20 pid=17873 ppid=17863 tid=1208239872
[ ]  END  P5 T21 pid=17873 ppid=17863 tid=1216632576
[ ]  END  P5 T19 pid=17873 ppid=17863 tid=1199847168
[ ]  END  P5 T16 pid=17873 ppid=17863 tid=1174669056
[ ] BEGIN P5 T32 pid=17873 ppid=17863 tid=1308952320
[ ] BEGIN P5 T1 pid=17873 ppid=17863 tid=1048778496
[ ]  END  P5 T1 pid=17873 ppid=17863 tid=1048778496
[ ]  END  P5 T32 pid=17873 ppid=17863 tid=1308952320
[ ] BEGIN P6 T0 pid=17916 ppid=17873 tid=1351051072
[ ]  END  P6 T0 pid=17916 ppid=17873 tid=1351051072
[ ]  END  P5 T0 pid=17873 ppid=17863 tid=1351051072
[ ]  END  P2 T0 pid=17863 ppid=17861 tid=1351051072
[ ]  END  P1 T0 pid=17861 ppid=17097 tid=1351051072