带有标志的 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
我尝试使用分叉而不是互斥锁来解决生产者消费者问题,我尝试使用信号量来纠正该行为。
#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