我有这个简单的代码,可以使用命名管道将值从子进程传递到父进程。代码:
App.php
我读到0666授予读和写权限,0200授予只写权限,0400授予只读权限,0000没有权限。但是,如果我将0666更改为其中任何一个,则代码可以正常工作。为什么会发生这种情况,我想念什么?
答案 0 :(得分:1)
正如我在评论中指出的那样,使用0666可以向用户,组和其他用户授予读取和写入权限,而0400意味着只有用户可以访问管道,并且他们只能从中读取(只有超级用户可以向其中写入数据) ),而0200表示只有用户可以访问该管道,并且他们只能对其进行写入(只有超级用户可以从中读取)。 (名称“ superuser”是“具有适当特权的用户”的简写,在基于Unix的系统上通常表示root
。)
这是您的代码版本,用于演示错误检查和报告。它使用可选的命令行参数作为要使用的FIFO的名称。它测试0666
,0400
,0200
和0
的每个模式。如果操作花费的时间太长,就会因超时而感到困惑。信号处理代码要注意avoid using printf()
in a signal handler,并且字符串具有足够的空间来容纳7位PID,例如在AIX上找到的。
该程序使用我的“标准错误报告功能”,该代码可在GitHub上的SOQ(堆栈溢出问题)存储库中以文件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不存在,则期望失败;如果不存在,则期望成功。如果FIFO存在但无法删除(因为它是目录,或者用户没有权限,或者其他原因),则错误报告检查mkfifo()
将处理问题。 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
$