gpt4 book ai didi

c - 使用多个进程和 pthread 处理文件

转载 作者:行者123 更新时间:2023-11-30 19:30:50 27 4
gpt4 key购买 nike

我在进程和线程之间的同步练习中遇到了麻烦。主进程应该创建N个子进程(使它们大致在同一时间启动),而子进程又应该创建M个线程。现在这些线程必须写入文件。一段时间后T主线程应该停止子进程并调用一个函数来查找哪个进程进行了更多的访问。文件中写入的内容或主进程如何决定哪一个写入更多并不重要。问题是:什么也没写。文件已创建,但没有任何反应,我不明白为什么。我在这上面浪费了一个下午,但我仍然不明白出了什么问题(尽管我怀疑 sigaction,因为我不希望使用它来使子进程停止)。请帮忙。这是代码

编辑:问题不应该出现在 init_file()parseOutput() 中,因为它们是教授给我的,经过测试后我就离开了它们没有变化

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <semaphore.h>
#include <pthread.h>
#include <errno.h>
#include <string.h>
#include <signal.h>

// macros for error handling
#include "common.h"

#define N 10 // child process count
#define M 10 // thread per child process count
#define T 3 // time to sleep for main process

#define FILENAME "accesses.log"
#define SEMFILENAME "/sem_file"
#define SEMPROCESSESNAME "/sem_proc"

/*
* data structure required by threads
*/
typedef struct thread_args_s {
unsigned int child_id;
unsigned int thread_id;
} thread_args_t;

/*
* parameters can be set also via command-line arguments
*/
int n = N, m = M, t = T;

/* TODO: declare as many semaphores as needed to implement
* the intended semantics, and choose unique identifiers for
* them (e.g., "/mysem_critical_section") */
sem_t * sem_file;
sem_t * sem_processes;
int running = 1;

/*
* Create a named semaphore with a given name, mode and initial value.
* Also, tries to remove any pre-existing semaphore with the same name.
*/
sem_t *create_named_semaphore(const char *name, mode_t mode, unsigned int value) {
printf("[Main] Creating named semaphore %s...", name);
fflush(stdout);

// TODO
sem_unlink(name);
sem_t *ret;
ret = sem_open(name, O_CREAT, mode, value);

if(ret == SEM_FAILED)
{
fprintf(stderr, "failed to open %s", name);
exit(EXIT_FAILURE);
}
printf("done!!!\n");
return ret;
}

/*
* Ensures that an empty file with given name exists.
*/
void init_file(const char *filename) {
printf("[Main] Initializing file %s...", filename);
fflush(stdout);
int fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0600);
if (fd<0) handle_error("error while initializing file");
close(fd);
printf("closed...file correctly initialized!!!\n");

sem_file = create_named_semaphore(SEMFILENAME, 0777, 1);
}
/*
* Child's signal handler
*/
void child_sig_handler(int signum) {
running = 0;
}


void parseOutput() {
// identify the child that accessed the file most times
int* access_stats = calloc(n, sizeof(int)); // initialized with zeros
printf("[Main] Opening file %s in read-only mode...", FILENAME);
fflush(stdout);
int fd = open(FILENAME, O_RDONLY);
if (fd < 0) handle_error("error while opening output file");
printf("ok, reading it and updating access stats...");
fflush(stdout);

size_t read_bytes;
int index;
do {
read_bytes = read(fd, &index, sizeof(int));
if (read_bytes > 0)
access_stats[index]++;
} while(read_bytes > 0);
printf("ok, closing it...");
fflush(stdout);

close(fd);
printf("closed!!!\n");

int max_child_id = -1, max_accesses = -1, i;
for (i = 0; i < n; i++) {
printf("[Main] Child %d accessed file %s %d times\n", i, FILENAME, access_stats[i]);
if (access_stats[i] > max_accesses) {
max_accesses = access_stats[i];
max_child_id = i;
}
}
printf("[Main] ===> The process that accessed the file most often is %d (%d accesses)\n", max_child_id, max_accesses);
free(access_stats);
}

void* thread_function(void* x) {
thread_args_t *args = (thread_args_t*)x;

/* TODO: protect the critical section using semaphore(s) as needed */
if(sem_wait(sem_file)) handle_error("failed to wait on sem_file");
// open file, write child identity and close file

int fd = open(FILENAME, O_WRONLY | O_APPEND);
if (fd < 0) handle_error("error while opening file");

printf("[Child#%d-Thread#%d] File %s opened in append mode!!!\n", args->child_id, args->thread_id, FILENAME);

write(fd, &(args->child_id), sizeof(int));
printf("[Child#%d-Thread#%d] %d appended to file %s opened in append mode!!!\n", args->child_id, args->thread_id, args->child_id, FILENAME);
close(fd);

if(sem_post(sem_file)) handle_error("failed to release sem_file");

printf("[Child#%d-Thread#%d] File %s closed!!!\n", args->child_id, args->thread_id, FILENAME);


pthread_exit(NULL);
}

void childProcess(int child_id) {
/* TODO: each child process notifies the main process that it
* is ready, then waits to be notified from the main in order
* to start. As long as the main process does not notify a
* termination event [hint: use sem_getvalue() here], the child
* process repeatedly creates m threads that execute function
* thread_function() and waits for their completion. When a
* notification has arrived, the child process notifies the main
* process that it is about to terminate, and releases any
* shared resources before exiting. */
sem_wait(sem_processes);

int i;
pthread_t threads[M];
while(running)
{
for(i = 0; i < M; i++)
if(pthread_create(threads+i, NULL, &thread_function, NULL)) handle_error("Failed to create pthread");
for(; i > 0; i ++)
if(pthread_join(threads[i], NULL)) handle_error("Failed to join pthread");
}
_exit(EXIT_SUCCESS);
}

void mainProcess() {
/* TODO: the main process waits for all the children to start,
* it notifies them to start their activities, and sleeps
* for some time t. Once it wakes up, it notifies the children
* to end their activities, and waits for their termination.
* Finally, it calls the parseOutput() method and releases
* any shared resources. */
int i;
unsigned t_left = T;
pid_t id, *childs_ids = malloc(sizeof(pid_t)*N);

sem_processes = create_named_semaphore(SEMPROCESSESNAME, 0777, 0);

struct sigaction act;
memset(&act, 0, sizeof(act));
act.sa_handler = &child_sig_handler;
sigaction(SIGTERM, &act, NULL);

for(i = 0; i < N; i++)
{
id = fork();
if(id < 0)
handle_error("Fork failed");
if(id == 0)
childProcess(i);
childs_ids[i] = id;
}
for(; i > 0; i--)
sem_post(sem_processes);

//Sleeps for T seconds
while((t_left = sleep(t_left)));

for(; i < N; i++)
{
kill(childs_ids[i], SIGTERM);
}

int status;
for(; i>0; i--)
if(wait(&status)< 0) handle_error("wait failed");
parseOutput();
}

int main(int argc, char **argv) {
// arguments
if (argc > 1) n = atoi(argv[1]);
if (argc > 2) m = atoi(argv[2]);
if (argc > 3) t = atoi(argv[3]);

// initialize the file
init_file(FILENAME);

/* TODO: initialize any semaphore needed in the implementation, and
* create N children where the i-th child calls childProcess(i); then
* the main process executes function mainProcess() once all the
* children have been created */
mainProcess();

if(sem_close(sem_processes)) handle_error("failed to close sem_processes");
if(sem_close(sem_file)) handle_error("failed to close sem_file");
if(sem_unlink(SEMPROCESSESNAME)) handle_error("failed to unlink sem_processes");
if(sem_unlink(SEMFILENAME)) handle_error("failed to unlink sem_file");
exit(EXIT_SUCCESS);
}

这是 shell 上的输出:

[Main] Child 0 accessed file accesses.log 0 times
[Main] Child 1 accessed file accesses.log 0 times
[Main] Child 2 accessed file accesses.log 0 times
[Main] Child 3 accessed file accesses.log 0 times
[Main] Child 4 accessed file accesses.log 0 times
[Main] Child 5 accessed file accesses.log 0 times
[Main] Child 6 accessed file accesses.log 0 times
[Main] Child 7 accessed file accesses.log 0 times
[Main] Child 8 accessed file accesses.log 0 times
[Main] Child 9 accessed file accesses.log 0 times
[Main] Child 10 accessed file accesses.log 0 times
[Main] Child 11 accessed file accesses.log 0 times
[Main] Child 12 accessed file accesses.log 0 times
[Main] Child 13 accessed file accesses.log 0 times
[Main] Child 14 accessed file accesses.log 0 times
[Main] Child 15 accessed file accesses.log 0 times
[Main] Child 16 accessed file accesses.log 0 times
[Main] Child 17 accessed file accesses.log 0 times
[Main] Child 18 accessed file accesses.log 0 times
[Main] Child 19 accessed file accesses.log 0 times
[Main] Child 20 accessed file accesses.log 0 times
[Main] Child 21 accessed file accesses.log 0 times
[Main] Child 22 accessed file accesses.log 0 times
[Main] Child 23 accessed file accesses.log 0 times
[Main] Child 24 accessed file accesses.log 0 times
[Main] Child 25 accessed file accesses.log 0 times
[Main] Child 26 accessed file accesses.log 0 times
[Main] Child 27 accessed file accesses.log 0 times
[Main] Child 28 accessed file accesses.log 0 times
[Main] Child 29 accessed file accesses.log 0 times
[Main] Child 30 accessed file accesses.log 0 times
[Main] Child 31 accessed file accesses.log 0 times
[Main] Child 32 accessed file accesses.log 0 times
[Main] Child 33 accessed file accesses.log 0 times
[Main] Child 34 accessed file accesses.log 0 times
[Main] Child 35 accessed file accesses.log 0 times
[Main] Child 36 accessed file accesses.log 0 times
[Main] Child 37 accessed file accesses.log 0 times
[Main] Child 38 accessed file accesses.log 0 times
[Main] Child 39 accessed file accesses.log 0 times
[Main] Child 40 accessed file accesses.log 0 times
[Main] Child 41 accessed file accesses.log 0 times
[Main] Child 42 accessed file accesses.log 0 times
[Main] Child 43 accessed file accesses.log 0 times
[Main] Child 44 accessed file accesses.log 0 times
[Main] Child 45 accessed file accesses.log 0 times
[Main] Child 46 accessed file accesses.log 0 times
[Main] Child 47 accessed file accesses.log 0 times
[Main] Child 48 accessed file accesses.log 0 times
[Main] Child 49 accessed file accesses.log 0 times
[Main] Child 50 accessed file accesses.log 0 times
[Main] Child 51 accessed file accesses.log 0 times
[Main] Child 52 accessed file accesses.log 0 times
[Main] Child 53 accessed file accesses.log 0 times
[Main] Child 54 accessed file accesses.log 0 times
[Main] Child 55 accessed file accesses.log 0 times
[Main] Child 56 accessed file accesses.log 0 times
[Main] Child 57 accessed file accesses.log 0 times
[Main] Child 58 accessed file accesses.log 0 times
[Main] Child 59 accessed file accesses.log 0 times
[Main] Child 60 accessed file accesses.log 0 times
[Main] Child 61 accessed file accesses.log 0 times
[Main] Child 62 accessed file accesses.log 0 times
[Main] Child 63 accessed file accesses.log 0 times
[Main] Child 64 accessed file accesses.log 0 times
[Main] Child 65 accessed file accesses.log 0 times
[Main] Child 66 accessed file accesses.log 0 times
[Main] Child 67 accessed file accesses.log 0 times
[Main] Child 68 accessed file accesses.log 0 times
[Main] Child 69 accessed file accesses.log 0 times
[Main] Child 70 accessed file accesses.log 0 times
[Main] Child 71 accessed file accesses.log 0 times
[Main] Child 72 accessed file accesses.log 0 times
[Main] Child 73 accessed file accesses.log 0 times
[Main] Child 74 accessed file accesses.log 0 times
[Main] Child 75 accessed file accesses.log 0 times
[Main] Child 76 accessed file accesses.log 0 times
[Main] Child 77 accessed file accesses.log 0 times
[Main] Child 78 accessed file accesses.log 0 times
[Main] Child 79 accessed file accesses.log 0 times
[Main] Child 80 accessed file accesses.log 0 times
[Main] Child 81 accessed file accesses.log 0 times
[Main] Child 82 accessed file accesses.log 0 times
[Main] Child 83 accessed file accesses.log 0 times
[Main] Child 84 accessed file accesses.log 0 times
[Main] Child 85 accessed file accesses.log 0 times
[Main] Child 86 accessed file accesses.log 0 times
[Main] Child 87 accessed file accesses.log 0 times
[Main] Child 88 accessed file accesses.log 0 times
[Main] Child 89 accessed file accesses.log 0 times
[Main] Child 90 accessed file accesses.log 0 times
[Main] Child 91 accessed file accesses.log 0 times
[Main] Child 92 accessed file accesses.log 0 times
[Main] Child 93 accessed file accesses.log 0 times
[Main] Child 94 accessed file accesses.log 0 times
[Main] Child 95 accessed file accesses.log 0 times
[Main] Child 96 accessed file accesses.log 0 times
[Main] Child 97 accessed file accesses.log 0 times
[Main] Child 98 accessed file accesses.log 0 times
[Main] Child 99 accessed file accesses.log 0 times
[Main] ===> The process that accessed the file most often is 0 (0 accesses)

这里也是common.h

#include <errno.h>

#include <stdio.h>

#include <string.h>



// macros for handling errors

#define handle_error_en(en, msg) do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0)

#define handle_error(msg) do { perror(msg); exit(EXIT_FAILURE); } while (0)

最佳答案

线程函数需要一个类型为 thread_args_t 的参数,而我传递的是 NULL。我什至不知道为什么它从未引发段错误。通过对 pthread_create 的正确输入,一切正常。

关于c - 使用多个进程和 pthread 处理文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50004029/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com