在标准文件上使用fcntl F_SETLKW是否合法?

在标准文件上使用fcntl F_SETLKW是否合法?,c,linux,synchronization,posix,C,Linux,Synchronization,Posix,我从主程序通过fork生成了多个进程,这意味着它们输出到同一个stdout(我想要)。但是,我需要以某种方式防止输出被交错。我已经使用fcntl锁来同步对日志文件的访问,所以我想将它也用于标准输出 然而,博客文章声称fcntl锁与[i-node,pid]对关联。你没有inode吗?我决定试试看 #include <unistd.h> #include <fcntl.h> #include <stdlib.h> #include <stdio.h>

我从主程序通过fork生成了多个进程,这意味着它们输出到同一个stdout(我想要)。但是,我需要以某种方式防止输出被交错。我已经使用fcntl锁来同步对日志文件的访问,所以我想将它也用于标准输出

然而,博客文章声称fcntl锁与[i-node,pid]对关联
。你没有inode吗?我决定试试看

#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/wait.h>

void do_log(const char *msg) {
    printf("%5ld: %s\n", getpid(), msg);
}

void try_lock(void) {
    do_log("Trying to lock stdout...");

    struct flock fl = {
        .l_type = F_WRLCK,
        .l_whence = SEEK_SET,
        .l_start = 0,
        .l_len = 0,
    };
    if (fcntl(STDOUT_FILENO, F_SETLKW, &fl) == -1) {
        perror("fcntl - lock");
        exit(1);
    }

    do_log("Stdout locked");
    sleep(2);
    do_log("Trying to unlock stdout...");

    fl.l_type = F_UNLCK;
    if (fcntl(STDOUT_FILENO, F_SETLKW, &fl) == -1) {
        perror("fcntl - unlock");
        exit(1);
    }

    do_log("Stdout unlocked");
}

int main(void) {
    if (fork()) {
        try_lock();
    } else {
        try_lock();
    }
    wait(NULL);
    return 0;
}
但是在fcntl的manpage中,我注意到
如果fildes引用类型化内存对象,则fcntl()函数的结果是未指定的。
我不知道这意味着什么

所以我想我有两个问题:

  • 在stdout上使用fcntl锁是否保证能正常工作
  • 如果答案是1。是的,关于
    [i-node,pid]
    的博文是错误的还是stdout实际上有i-node
  • inode编号(以及设备编号)纯粹是文件的唯一标识符。在这个术语的现代用法中,它与磁盘上的文件系统结构无关。所有文件(文件描述符指打开文件的实例)都有一个inode编号,并且对它们执行
    fcntl
    至少“有意义”。但是,根据POSIX:

    常规文件应支持记录锁定,其他文件也可支持记录锁定

    可能有一些文件类型Linux不支持锁;我不确定

    还请注意,锁定纯粹是建议性的-如果执行写入操作的进程在执行访问之前不尝试获取锁定,则锁定没有任何效果


    它可能更有意义,特别是如果您使用
    fork
    而不使用
    exec
    ,通过共享内存进行锁定。分叉之前,
    mmap
    a
    MAP|ANON | MAP|u SHARED
    区域并在其中设置进程共享互斥体。如果任何进程可能意外死亡,您可以将其设置为健壮的互斥对象。这是可以保证工作的,而且应该更快,因为除了锁争用之外,这纯粹是一个用户空间操作。

    标准输入不太可能是“类型化内存对象”。这需要特别的工作来建立它。
    17156: Trying to lock stdout...
    17155: Trying to lock stdout...
    17155: Stdout locked
    17155: Trying to unlock stdout...
    17155: Stdout unlocked
    17156: Stdout locked
    17156: Trying to unlock stdout...
    17156: Stdout unlocked