C 代码在创建第一个 pthread (Linux) 后停止

标签 c linux

我的代码应该多次执行 start_hydrogenstart_carbon 函数,但只从一个线程的执行输出到控制台,然后程序挂起。我想我可能错误地启动了线程。我是 C 的新手,所以如果需要其他信息,请告诉我。请注意,打印了 this line is reached 输出。

#include "main.h"

void *start_hydrogen(void *);//executes hydrogen.c
void *start_carbon(void *);//executes carbon.c

struct threadInfo {
    int threadId;
};

struct threadInfo hydrogenIDs[NUM_H];
struct threadInfo carbonIDs[NUM_C];

int main() {
    int semid, shmid;//semaphore memory id, shared memory id
    unsigned short seminit[NUM_SEMS];//used to initialize semaphores
    struct common *shared;//pointer to shared data structure
    union semun semctlarg;//used to initialize semaphores

    pthread_t hydrogen[NUM_H];
    pthread_t carbon[NUM_C];
    pthread_attr_t attr;
    void *exit_status;

    //Creating a set of attributes to send to the threads
    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);

    //get semaphore memory id
    if ((semid = semget(SEMKEY, NUM_SEMS, IPC_CREAT|0777)) < 0) {
        perror("semget");
        exit(EXIT_FAILURE);
    }

    printf("THE PROGRAM IS STARTING\n\n");

    seminit[MUTEX] = 1;//initialize mutex semaphore count to 1
    seminit[SH] = 0;//initialize hyrdrogen semaphore count to 0
    seminit[SC] = 0;//initialize carbon semaphore count to 0
    semctlarg.array = seminit;//set control array

    //apply initialization
    if ((semctl(semid, NUM_SEMS, SETALL, semctlarg)) < 0) {
        perror("semctl");
        exit(EXIT_FAILURE);
    }

    //get shared memory id
    if ((shmid = shmget(SHMKEY, 1*K, IPC_CREAT|0777)) < 0) {
        perror("shmget");
        exit(EXIT_FAILURE);
    }

    //retrieve pointer to shared data structure
    if ((shared = (struct common *)shmat(shmid, 0, 0)) < 0) {
        perror("shmat");
        exit(EXIT_FAILURE);
    }

    //initialize shared data structure variables
    shared->waiting_H = 0;
    shared->waiting_C = 0;

    int retVal;//used to check return value of fork()

    // spawn 20 Hydrogens
    for (int i=0; i<NUM_H; i++) {
        // if ((retVal = fork()) == 0) {
        //  hydrogen();
        //  fflush(stdout);
        //  printf("New Hydrogen process created\n");
        //  fflush(stdout);
        // } else if (retVal < 0) {
        //  perror("fork");
        //  exit(EXIT_FAILURE);
        // }
        hydrogenIDs[i].threadId = i;
        retVal = pthread_create(&hydrogen[i], &attr, start_hydrogen, (void*) &hydrogenIDs[i]);
        if (retVal != 0) {
            perror("pthread_create");
            exit(EXIT_FAILURE);
        }
    }

    printf("this line reached\n");

    // spawn 5 Carbons
    for (int i=0; i<NUM_C; i++) {
        // if ((retVal = fork()) == 0) {
        //  carbon();
        //  fflush(stdout);
        //  printf("New Hydrogen process created\n");
        //  fflush(stdout);
        // } else if (retVal < 0) {
        //  perror("fork");
        //  exit(EXIT_FAILURE);
        // }
        carbonIDs[i].threadId = i;
        retVal = pthread_create(&carbon[i], &attr, start_carbon, (void*) &carbonIDs[i]);
        if (retVal != 0) {
            perror("pthread_create");
            exit(EXIT_FAILURE);
        }
    }

    //wait for all car processes to finish
    // for (int i = 0; i < 25; ++i) {
    //  if (wait(0) < 0) {
    //      perror("wait");
    //      exit(EXIT_FAILURE);
    //  }
    // }

    //Wait for all the threads to finish
    for(int i = 0; i < NUM_C; i++)
    {
        pthread_join(carbon[i], &exit_status);
    }

    for(int i = 0; i < NUM_H; i++)
    {
        pthread_join(hydrogen[i], &exit_status);
    }



    printf("All atoms have crossed!\n");

        //delete semaphores
    if (semctl(semid, NUM_SEMS, IPC_RMID, 0) < 0) {
        perror("semctl");
        exit(EXIT_FAILURE);
    }

    //delete shared memory
    if (shmctl(shmid, IPC_RMID, 0) < 0) {
        perror("shmctl");
        exit(EXIT_FAILURE);
    }

    return EXIT_SUCCESS;
}

原始start_carbon()start_hydrogen() 函数

void *start_carbon(void* arg) {
    execl("carbon", "carbon", 0);
    perror("execl");
    exit(EXIT_FAILURE);//if exec returns there was an error
}

void *start_hydrogen(void* arg) {
    execl("hydrogen", "hydrogen", 0);
    perror("execl");
    exit(EXIT_FAILURE);//if exec returns there was an error
}

修改的start_hydrogen()start_carbon() 函数

在收到有关使用 execl() 不当的反馈后,我将 start_hydrogen()start_carbon() 函数更改为:

void *start_hydrogen(void* arg) {
    struct common *shared;//pointer to shared data structure

    int semid, shmid;//semaphore memory id, shared memory id

    int pid = getpid();

    //get semaphore memory id
    if ((semid = semget(SEMKEY, NUM_SEMS, 0777)) < 0) {
        perror("semget");
        exit(EXIT_FAILURE);
    }

    //get shared memory id
    if ((shmid = shmget(SHMKEY, 1*K, 0777)) < 0) {
        perror("shmget");
        exit(EXIT_FAILURE);
    }

    //get pointer to shared data structure
    if ((shared = (struct common *)shmat(shmid, 0, 0)) < 0) {
        perror("shmat");
        exit(EXIT_FAILURE);
    }

    // acquire lock on mutex before accessing shared memory
    semWait(semid, MUTEX);

    fflush(stdout);
    printf("Hydrogen atom, pid %d, arrives at barrier\n", pid);
    printf("Currently %d Hydrogens and %d Carbons waiting\n", shared->waiting_H + 1, shared->waiting_C);
    fflush(stdout);

    // if enough C and H is waiting, continue past barrier
    if (shared->waiting_H >= 3 
        && shared->waiting_C >= 1) {
        // release 3 H
        for (int i=0; i < 3; i++) {
            semSignal(semid, SH);
        }
        shared->waiting_H -= 3;
        semSignal(semid, SC); // release 1 C
        shared->waiting_C -= 1;

        fflush(stdout);
        printf("\nHello from %d, 1 CH4 molecule has xed the barrier\n\n", pid);
        fflush(stdout);
        // release lock on mutex
        semSignal(semid, MUTEX);
    } else {
        // not enough C or H is waiting, so wait at barrier
        shared->waiting_H += 1;
        // relaese lock on mutex
        semSignal(semid, MUTEX);
        semWait(semid, SH);
    }
    pthread_exit(NULL);
}

void *start_carbon(void* arg) {
    struct common *shared;//pointer to shared data structure

    int semid, shmid;//semaphore memory id, shared memory id

    int pid = getpid();

    //get semaphore memory id
    if ((semid = semget(SEMKEY, NUM_SEMS, 0777)) < 0) {
        perror("semget");
        exit(EXIT_FAILURE);
    }

    //get shared memory id
    if ((shmid = shmget(SHMKEY, 1*K, 0777)) < 0) {
        perror("shmget");
        exit(EXIT_FAILURE);
    }

    //get pointer to shared data structure
    if ((shared = (struct common *)shmat(shmid, 0, 0)) < 0) {
        perror("shmat");
        exit(EXIT_FAILURE);
    }

    // acquire lock on mutex before accessing shared memory
    semWait(semid, MUTEX);

    fflush(stdout);
    printf("Hydrogen atom, pid %d, arrives at barrier\n", pid);
    printf("Currently %d Hydrogens and %d Carbons waiting\n", shared->waiting_H + 1, shared->waiting_C);
    fflush(stdout);

    // if enough C and H is waiting, continue past barrier
    if (shared->waiting_H >= 3 
        && shared->waiting_C >= 1) {
        // release 3 H
        for (int i=0; i < 3; i++) {
            semSignal(semid, SH);
        }
        shared->waiting_H -= 3;
        semSignal(semid, SC); // release 1 C
        shared->waiting_C -= 1;

        fflush(stdout);
        printf("\nHello from %d, 1 CH4 molecule has xed the barrier\n\n", pid);
        fflush(stdout);
        // release lock on mutex
        semSignal(semid, MUTEX);
    } else {
        // not enough C or H is waiting, so wait at barrier
        shared->waiting_H += 1;
        // relaese lock on mutex
        semSignal(semid, MUTEX);
        semWait(semid, SH);
    }
    pthread_exit(NULL);
}

最佳答案

来自 execl() 的手册页,

The exec() family of functions replaces the current process image with a new process image.

The exec() functions only return if an error has occurred.

如果要用execl()调用外部程序,应该先fork()父进程,让父进程继续运行。请注意,在这种情况下,线程实际上不会执行您想要的操作。

关于C 代码在创建第一个 pthread (Linux) 后停止,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36584832/

相关文章:

c - Linux 的 kbhit()[和 getch()] 问题

php - 在 XAMPP for Linux 中使用 mailtodisk/mailoutput

c - 双核 ARMv7 处理器中的并行处理

c - 将数值二维数组保存到图像

使用 GNU 工具链 (gcc/ld) 从静态库创建共享库

linux - Jinja 模板中的 Ansible 多个事实

linux - PostgreSQL:CURRENT_TIMESTAMP 和 CLOCK_TIMESTAMP 解决方案:Windows 与 Linux?

c - 如何让 MPI 中的所有等级向等级 0 发送一个值,然后阻塞接收所有等级?

linux - 如何设置cron来显示gui应用程序

java - 在一个路径中一起解析符号链接(symbolic link)和 ".."