У меня проблемы с этим упражнением синхронизации между процессами и потоками. Основной процесс должен создавать 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);
}
А вот вывод на оболочку:
[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)
Также здесь часто встречаются.
#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)