Как я отметил в комментариях, использование 0666 дает разрешение на чтение и запись пользователю, группе и другим, тогда как 0400 означает, что только пользователь может получить доступ к каналу, и они могут только читать из него (только суперпользователь может писать в него ) в то время как 0200 означает, что только пользователь может получить доступ к каналу, и они могут только писать в него (только суперпользователь может читать из него). (Название «superuser» является сокращением для «пользователя с соответствующими привилегиями», что обычно означает root
в системах на основе Unix.)
Вот версия вашего кода, которая демонстрирует проверку ошибок и создание отчетов. Он принимает необязательный аргумент командной строки для имени FIFO, который он будет использовать. Он тестирует каждый из режимов 0666
, 0400
, 0200
и 0
. Это запутано с тайм-аутом, если операция занимает слишком много времени. Код обработки сигналов заботится о том, чтобы избегал использования printf()
в обработчике сигналов , а в строке достаточно места для 7-значных идентификаторов PID, таких как в AIX.
Программа использует мои «стандартные функции отчетов об ошибках», код которых доступен в моем репозитории SOQ (Вопросы о переполнении стека) на GitHub в виде файлов stderr.c
и stderr.h
в src / libsoq подкаталог. Их использование упрощает код обработки ошибок. Имена функций, содержащие rem
, делают замечания (и продолжают); те, которые заканчиваются err
, выходят после сообщения об ошибке. Опции сообщают время с точностью до миллисекунды и обеспечивают отображение PID в сообщении об ошибке.
#include <fcntl.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <time.h>
#include <unistd.h>
#include "stderr.h"
static void test_fifo(const char *fifo, int mode);
static void alarm_handler(int signum);
int main(int argc, char **argv)
{
err_setarg0(argv[0]);
err_setlogopts(ERR_PID|ERR_MILLI);
int modes[] = { 0666, 0400, 0200, 0 };
enum { NUM_MODES = sizeof(modes) / sizeof(modes[0]) };
char *myfifo = "/tmp/myfifo";
if (argc > 1)
myfifo = argv[1];
signal(SIGALRM, alarm_handler);
for (int i = 0; i < NUM_MODES; i++)
{
putchar('\n');
test_fifo(myfifo, modes[i]);
int corpse;
int status;
while ((corpse = wait(&status)) > 0)
err_remark("Child %d exited with status 0x%.4X\n", corpse, status);
}
return 0;
}
static void set_pid(int pid, char *str)
{
if (pid / 10 > 0)
set_pid(pid / 10, str + 1);
else
{
str[1] = '\n';
str[2] = '\0';
}
*str = (pid % 10) + '0';
}
static void alarm_handler(int signum)
{
char msg[] = "Signal ?? received by ???????\n";
msg[7] = (signum / 10) > 0 ? (signum / 10) + '0' : ' ';
msg[8] = (signum % 10) + '0';
set_pid(getpid(), &msg[22]);
write(0, msg, strlen(msg));
}
static void test_fifo(const char *fifo, int mode)
{
unlink(fifo);
if (mkfifo(fifo, mode) != 0)
{
err_sysrem("failed to create FIFO '%s' with mode %0o\n", fifo, mode);
return;
}
pid_t c = fork();
/* With ERR_PID set, the PID is reported automatically */
err_remark("(PPID %d) at work\n", (int)getppid());
if (c == 0)
{
/* Child */
srand(time(0));
int val = rand() % 100;
alarm(10);
int fd = open(fifo, O_WRONLY);
if (fd < 0)
err_syserr("failed to open FIFO '%s' for writing\n", fifo);
if (write(fd, &val, sizeof(val)) != sizeof(val))
err_syserr("failed to write to FIFO '%s'\n", fifo);
printf("Wrote %d to FIFO '%s'\n", val, fifo);
close(fd);
exit(0);
}
if (c > 0)
{
/* Parent */
alarm(10);
int fd = open(fifo, O_RDONLY);
if (fd < 0)
{
err_sysrem("failed to open FIFO '%s' for reading\n", fifo);
return;
}
int val;
if (read(fd, &val, sizeof(val)) != sizeof(val))
{
err_sysrem("failed to write to FIFO '%s'\n", fifo);
return;
}
printf("read value %d from FIFO '%s'\n", val, fifo);
close(fd);
if (unlink(fifo) != 0)
err_sysrem("failed to remove FIFO '%s'\n", fifo);
}
}
Я сознательно решил не сообщать об ошибках от close()
; вы ничего не можете сделать, если close()
все равно сообщит о сбое. Первый unlink()
не проверен; ожидается, что он потерпит неудачу, если FIFO не существует, и будет успешным, если он существует. Проверка отчета об ошибках mkfifo()
будет обрабатывать проблемы, если FIFO существует, но не может быть удален (потому что это каталог, или у пользователя нет разрешения, или что-то еще). Расположение цикла wait()
помогает обеспечить отображение сообщений об ошибках и т. Д., Даже если родительский процесс завершается быстро, поскольку он не может открыть FIFO, но дочерний процесс завершается медленно, поскольку он может открыть FIFO.
Пример вывода (я назвал программу fifo37
, а исходный код был в fifo37.c
):
$ ./fifo37
fifo37: 2019-05-03 14:58:48.612 - pid=94485: (PPID 51845) at work
fifo37: 2019-05-03 14:58:48.612 - pid=94486: (PPID 94485) at work
Wrote 1 to FIFO '/tmp/myfifo'
read value 1 from FIFO '/tmp/myfifo'
fifo37: 2019-05-03 14:58:48.614 - pid=94485: Child 94486 exited with status 0x0000
fifo37: 2019-05-03 14:58:48.614 - pid=94485: (PPID 51845) at work
fifo37: 2019-05-03 14:58:48.614 - pid=94487: (PPID 94485) at work
fifo37: 2019-05-03 14:58:48.614 - pid=94487: failed to open FIFO '/tmp/myfifo' for writing
error (13) Permission denied
Signal 14 received by 58449
fifo37: 2019-05-03 14:58:58.615 - pid=94485: failed to open FIFO '/tmp/myfifo' for reading
error (4) Interrupted system call
fifo37: 2019-05-03 14:58:58.615 - pid=94485: Child 94487 exited with status 0x0100
fifo37: 2019-05-03 14:58:58.616 - pid=94485: (PPID 51845) at work
fifo37: 2019-05-03 14:58:58.616 - pid=94485: failed to open FIFO '/tmp/myfifo' for reading
error (13) Permission denied
fifo37: 2019-05-03 14:58:58.616 - pid=94488: (PPID 94485) at work
Signal 14 received by 58449
Signal 14 received by 88449
fifo37: 2019-05-03 14:59:08.619 - pid=94488: failed to open FIFO '/tmp/myfifo' for writing
error (4) Interrupted system call
fifo37: 2019-05-03 14:59:08.621 - pid=94485: Child 94488 exited with status 0x0100
fifo37: 2019-05-03 14:59:08.621 - pid=94485: (PPID 51845) at work
fifo37: 2019-05-03 14:59:08.621 - pid=94485: failed to open FIFO '/tmp/myfifo' for reading
error (13) Permission denied
fifo37: 2019-05-03 14:59:08.621 - pid=94489: (PPID 94485) at work
fifo37: 2019-05-03 14:59:08.622 - pid=94489: failed to open FIFO '/tmp/myfifo' for writing
error (13) Permission denied
fifo37: 2019-05-03 14:59:08.622 - pid=94485: Child 94489 exited with status 0x0100
$