C代码在创建第一个pthread(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 STARTINGnn");
    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 createdn");
        //  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 reachedn");
    // spawn 5 Carbons
    for (int i=0; i<NUM_C; i++) {
        // if ((retVal = fork()) == 0) {
        //  carbon();
        //  fflush(stdout);
        //  printf("New Hydrogen process createdn");
        //  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 barriern", pid);
    printf("Currently %d Hydrogens and %d Carbons waitingn", 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 barriernn", 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 barriern", pid);
    printf("Currently %d Hydrogens and %d Carbons waitingn", 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 barriernn", 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()的手册页,

exec()函数族将当前进程映像替换为新的进程映像。

exec()函数仅在发生错误时返回。

如果要使用execl()调用外部程序,则应首先派生父进程以允许父进程继续运行。请注意,在这种情况下,线程确实不会执行您想要的操作。

最新更新