带有标志的 C 信号量数组编译器错误

c semaphore array compiler error with flags

我尝试使用分叉而不是互斥锁来解决生产者消费者问题,我尝试使用信号量来纠正该行为。

#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h> // for semathore obviously
#include <string.h>
#include <sys/types.h>
#include <sys/shm.h>
#include <errno.h>
#include <sys/wait.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <ctype.h>
#include <limits.h> // for INT_MAX, INT_MIN
#include <stdlib.h> // for strtol
#include <stdint.h> // for uint64_t

#define DO_OR_DIE(x, s) \
    do                  \
    {                   \
        if ((x) < 0)    \
        {               \
            perror(s);  \
            exit(1);    \
        }               \
    } while (0)

int main(int argc, char *argv[])
{
    if (argc != 3)
    {
        printf("Usage: ./task1 producer(number) consumer(number)\n");
        return EXIT_FAILURE;
    }

    char *p;

    errno = 0;
    long producer = strtol(argv[1], &p, 10);

    if (errno != 0 || *p != '[=10=]' || producer > INT_MAX || producer < INT_MIN)
    {
        // error handling
        printf("producer fail\n");
        printf("Usage: ./task1 producer(number) consumer(number)\n");
        return EXIT_FAILURE;
    }

    long consumer = strtol(argv[2], &p, 10);

    if (errno != 0 || *p != '[=10=]' || consumer > INT_MAX || consumer < INT_MIN)
    {
        // error handling
        printf("consumer fail\n");
        printf("Usage: ./task1 producer(number) consumer(number)\n");
        return EXIT_FAILURE;
    }

    if (consumer < 1 || producer < 1)
    {
        printf("number must be greater then 0!\n");
        return EXIT_FAILURE;
    }

    // input is correct and we can continue with the shared memory we need of size consumer!
    uint64_t *sharedmemory = mmap(NULL, (consumer + 1) * sizeof(uint64_t), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0); // share memory

    if (sharedmemory == MAP_FAILED) 
        {
            perror("mmap failed");
            exit(EXIT_FAILURE);
        }

    uint64_t *array = sharedmemory;

    // creating sem array with every element being a sem to check if it is used or not.
    sem_t *sema = mmap(NULL, sizeof(sema) * consumer, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);

    if (sema == MAP_FAILED) 
    {
        perror("mmap failed");
        exit(EXIT_FAILURE);
    }

    for (int i = 0; i < consumer; ++i)
    {
        // creating sem entry for every array element
        if (sem_init(&sema + i, 1, 0) < 0)
        {
            perror("sem_init failed");
            exit(EXIT_FAILURE);
        }
    }

    // after creating shared memory fork 2 times
    pid_t pid = fork();
    DO_OR_DIE(pid, "fork1 failed!\n");

    if (pid == 0)
    {
        // child process 1

        // if Producer > Consumer then wrap around the ring buffer
        for (int i = 0; i < producer; ++i)
        {
            sem_wait(&sema[i]);
            // wrap around in ring buffer (i % buffer)
            array[i % consumer] = i + 1;
            sem_post(&sema[i]);
        }
        munmap(sharedmemory, (consumer + 1) * sizeof(uint64_t));
    }

    pid = fork();
    DO_OR_DIE(pid, "fork2 failed!\n");

    if (pid == 0)
    {
        // child process 2
        unsigned long long result = 0;

        for (int i = 0; i < producer; ++i)
        {
            sem_wait(&sema[i]);
            // read from shared memory
            result += array[i];
            sem_post(&sema[i]);
        }
        array[consumer + 1] = result;
        munmap(sharedmemory, (consumer + 1) * sizeof(uint64_t)); // sets the memory free (mmap)
    }

    // waiting for children
    while ((pid = wait(NULL)) != -1)
        ;

    // printing the result
    printf("%ld\n", array[consumer + 1]);

    // cleanup
    munmap(sharedmemory, (consumer + 1) * sizeof(uint64_t));

    for (int i = 0; i < consumer; ++i)
    {
        // creating sem entry for every array element
        sem_destroy(&sema+i);
    }

    return EXIT_SUCCESS;
}

我也使用以下标志进行编译:

-Wall -Wextra -lpthread -lrt -lm

我目前面临的问题是这条错误信息:

cc  prodcons.o  -o prodcons
/usr/bin/ld: prodcons.o: in function `main':
prodcons.c:(.text+0x230): undefined reference to `sem_init'
/usr/bin/ld: prodcons.c:(.text+0x2ae): undefined reference to `sem_wait'
/usr/bin/ld: prodcons.c:(.text+0x2ef): undefined reference to `sem_post'
/usr/bin/ld: prodcons.c:(.text+0x377): undefined reference to `sem_wait'
/usr/bin/ld: prodcons.c:(.text+0x3aa): undefined reference to `sem_post'
/usr/bin/ld: prodcons.c:(.text+0x47f): undefined reference to `sem_destroy'
collect2: error: ld returned 1 exit status
make: *** [Makefile:6: prodcons] Error 1

我是不是遗漏了一个 header 还是我实现的信号量数组有误?

您看到的错误来自链接器。它无法在正在搜索的当前库中找到符号。

我们需要添加正确的 pthreads 库(参见 man sem_wait)。它想要 -lpthread

因此,重新编译:

cc prodcons.o -o prodcons -lpthread