我正在编写一个程序,使用5个线程查找最高为4294967295(unsigned int
)的素数。每个线程获取一系列数字以使用IsPrime()
函数进行检查(我从代码中删除了函数,因为它不是代码中断的地方),如果数字是素数,它会将数字放在命名共享中内存文件,大小为500 MB。为了确保程序正常工作,我从小范围的数字开始:0到25.因此每个线程获得5个数字来检查并将其放入映射文件中。这是代码:
#define _BSD_SOURCE
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <math.h>
#include <unistd.h>
#include <pthread.h>
/* The program is using 5 threads to find prime numbers.
therefore, each thread is responsible for finding the numbers
with in a specific range: unsigned int / 5
*/
#define THREAD_1_BEGIN 0
#define THREAD_1_END 5
#define THREAD_2_BEGIN 6
#define THREAD_2_END 10
#define THREAD_3_BEGIN 11
#define THREAD_3_END 15
#define THREAD_4_BEGIN 16
#define THREAD_4_END 20
#define THREAD_5_BEGIN 21
#define THREAD_5_END 25
// The shared variable to hold the total number of primes.
unsigned int totalPrimes = 0;
// Shared memory variables
unsigned char *bitmap;
unsigned int bitmap_size = 4294967295 / 8 + 1; // size of unsigned int
unsigned int *prime_numbers;
unsigned int object_size = 1024 * 1024 * 500; // 500 MB
void *addr;
// Threads
pthread_t threads[5];
pthread_mutex_t total_Mutex;
void *ThreadWorker(void *threadId);
int IsPrime(unsigned int number);
void *mount_shmem(char *path, unsigned int object_size);
int main(int argc, char **argv)
{
int i;
void *status;
// Set the threads attributes and mutex
pthread_attr_t attr;
pthread_mutex_init(&total_Mutex, NULL);
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
// Set the shared memory
addr = mount_shmem("threadedshm", object_size);
bitmap = addr;
prime_numbers = (unsigned int*)(bitmap + bitmap_size);
for(i = 0; i<5; i++){
pthread_create(&threads[i], &attr, ThreadWorker, (void *)i);
}
pthread_attr_destroy(&attr);
// Wait for each thread
for(i = 0; i<5; i++){
pthread_join(threads[i], &status);
}
printf("\n TOTAL: %u \n", totalPrimes);
pthread_mutex_destroy(&total_Mutex);
pthread_exit(NULL);
}
void *ThreadWorker(void *threadId)
{
int pos = (int) threadId;
unsigned int t1;
unsigned int t2;
unsigned int t3;
unsigned int t4;
unsigned int t5;
if(pos == 0){
for(t1 = THREAD_1_BEGIN; t1 <= THREAD_1_END; t1++){
if(IsPrime(t1)){
printf("Thread 1: %u\n", t1);
// put it in the shared memory file
prime_numbers[totalPrimes] = t1;
// Increment the counter by 1
pthread_mutex_lock(&total_Mutex);
totalPrimes++;
pthread_mutex_unlock(&total_Mutex);
}
}
}else if(pos == 1){
for(t2 = THREAD_2_BEGIN; t2 <= THREAD_2_END; t2++){
if(IsPrime(t2)){
printf("Thread 2: %u\n", t2);
// put it in the shared memory file
prime_numbers[totalPrimes] = t2;
// Increment the counter by 1
pthread_mutex_lock(&total_Mutex);
totalPrimes++;
pthread_mutex_unlock(&total_Mutex);
}
}
}else if(pos == 2){
for(t3 = THREAD_3_BEGIN; t3 <= THREAD_3_END; t3++){
if(IsPrime(t3)){
printf("Thread 3: %u\n", t3);
// put it in the shared memory file
prime_numbers[totalPrimes] = t3;
// Increment the counter by 1
pthread_mutex_lock(&total_Mutex);
totalPrimes++;
pthread_mutex_unlock(&total_Mutex);
}
}
}else if(pos == 3){
for(t4 = THREAD_4_BEGIN; t4 <= THREAD_4_END; t4++){
if(IsPrime(t4)){
printf("Thread 4: %u\n", t4);
// put it in the shared memory file
prime_numbers[totalPrimes] = t4;
// Increment the counter by 1
pthread_mutex_lock(&total_Mutex);
totalPrimes++;
pthread_mutex_unlock(&total_Mutex);
printf("Thread 4: %u\n", t4);
// put it in the shared memory file
prime_numbers[totalPrimes] = t4;
// Increment the counter by 1
pthread_mutex_lock(&total_Mutex);
totalPrimes++;
pthread_mutex_unlock(&total_Mutex);
}
}
}else if(pos == 4){
for(t5 = THREAD_5_BEGIN; t5 <= THREAD_5_END; t5++){
if(IsPrime(t5)){
printf("Thread 5: %u\n", t5);
// put it in the shared memory file
prime_numbers[totalPrimes] = t5;
// Increment the counter by 1
pthread_mutex_lock(&total_Mutex);
totalPrimes++;
pthread_mutex_unlock(&total_Mutex);
}
}
}
pthread_exit((void*) 0);
}
void *mount_shmem(char *path, unsigned int object_size){
int shmem_fd;
void *addr;
// create and resize the file
shmem_fd = shm_open(path, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
if (shmem_fd == -1){
fprintf(stdout, "failed to open shared memory object\n");
exit(EXIT_FAILURE);
}
// resize it to 500 MB
if (ftruncate(shmem_fd, object_size) == -1){
fprintf(stdout, "failed to resize shared memory object\n");
exit(EXIT_FAILURE);
}
addr = mmap(NULL, object_size, PROT_READ | PROT_WRITE, MAP_SHARED, shmem_fd, 0);
if (addr == MAP_FAILED){
fprintf(stdout, "failed to map shared memory object\n");
exit(EXIT_FAILURE);
}
return addr;
}
但是,在将数字插入数组(prime_numbers[totalPrimes] = t1;
)时,我遇到了分段错误错误。启动共享内存文件时,我无法弄清楚我做错了什么。我只使用一个线程尝试了它,因为我怀疑它可能是一个互斥问题,其中几个线程同时尝试更新文件,但这不是问题(我知道我最终需要互斥或信号量)。任何帮助将不胜感激。
答案 0 :(得分:3)
这一行:
prime_numbers = (unsigned int*)(bitmap + bitmap_size);
将prime_numbers
设置为远远超出bitmap
指向的共享内存区域的范围(这是导致崩溃的原因)。
你也有一个竞争条件,在这样的代码中:
// put it in the shared memory file
prime_numbers[totalPrimes] = t1;
// Increment the counter by 1
pthread_mutex_lock(&total_Mutex);
totalPrimes++;
pthread_mutex_unlock(&total_Mutex);
由于您在锁外部读取totalPrimes
以确定要写入的数组索引,因此两个线程可以写入相同的数组索引,从而导致更新丢失。您可以通过在执行增量时获取要写入的数组索引来解决此问题:
// Increment the counter by 1
pthread_mutex_lock(&total_Mutex);
thisPrime = totalPrimes++;
pthread_mutex_unlock(&total_Mutex);
// put it in the shared memory file
prime_numbers[thisPrime] = t1;