为什么我将STD_OUT重定向到一个文件,并在STD_OUT上写入数据时,该文件保持为空?

3

我无法解决标准输出的问题,我的操作系统是Unix。在Unix中,STD_IN = 0、STD_OUT = 1、STD_ERR = 2,基本上我尝试关闭与标准输出相关联的描述符,然后用我想要写入的文件的描述符覆盖它,但是当我打开文件时它是空的。

代码:

#include<fcntl.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<unistd.h>
/*special file's descriptor  --use it or constants in unistd.h-- */
#define STD_IN 0 /*standard input stream*/
#define STD_OUT 1 /*standard output stream*/
#define STD_ERR 2 /*standard output-error stream*/

int main(unsigned int num_of_args, char** args)
{
    if(num_of_args != 3)
    {
        write(STD_ERR, "Few argouments.\nThe use  = ./executable <message> <file>\n", 69);
        return -1;
    }

    int file_des= open(args[2],  O_CREAT,  0640);

    if(file_des < 0)
    {
        write(STD_ERR, "Error, we couldn't open file.\n", 31);
        return -1;
    }

    //I close the descriptor associated with STD_OUT
    close(STD_OUT);

    //I copy the descriptor associated with fil_des on the first available descriptor(so STD_OUT)
    dup(file_des);

    write(STD_OUT, args[1], sizeof(args[1]));

    close(file_des);

    return 0;
}

应该没问题,我没有看到任何错误,但是当我打开文件时,我找不到写的消息。为什么?帮帮我。


1
你希望dup会重用1,但没有检查返回值。 - stark
@stark 如果 STDOUT_FILENO 或者 1close() 关闭了,那么可用的最小编号文件描述符将会是 1。在这种情况下,dup() 保证返回 1:"除非另有规定,否则打开一个或多个文件描述符的所有函数都应在每次分配时原子地分配调用进程中尚未打开的最低编号可用文件描述符。" - Andrew Henle
2个回答

2

这段代码是不正确的:

int file_des= open(args[2],  O_CREAT,  0640);

根据 POSIX 中 open() 的文档(请注意加粗部分 - 我进行了加粗):

SYNOPSIS

#include <sys/stat.h>
#include <fcntl.h>

int open(const char *path, int oflag, ...);
int openat(int fd, const char *path, int oflag, ...);

DESCRIPTION ...

Values for oflag are constructed by a bitwise-inclusive OR of flags from the following list, defined in <fcntl.h>. Applications shall specify exactly one of the first five values (file access modes) below in the value of oflag:

O_EXEC
    Open for execute only (non-directory files). The result is unspecified if this flag is applied to a directory.
O_RDONLY
    Open for reading only.
O_RDWR
    Open for reading and writing. The result is undefined if this flag is applied to a FIFO.
O_SEARCH
    Open directory for search only. The result is unspecified if this flag is applied to a non-directory file.
O_WRONLY
    Open for writing only.
您的open()调用需要包含O_WRONLYO_RDWR,因为您正在写入文件:
int file_des= open(args[2],  O_CREAT | O_WRONLY,  0640);

1
这是正确的,我建议您在回答中进行编辑并进一步明确一步。OP的文件为空,因为write由于EBADF失败,因为fd#1(成功dup的返回)错误地以只读方式打开。正如您所说,调用open是不正确的,因为它省略了一个必需的标志。任何事情都可能发生,但在这种情况下,OP的系统可能将O_RDONLY定义为0x0(像许多其他系统一样),这意味着错误地省略这些标志与指定O_RDONLY相同。 - pilcrow
@pilcrow 你说的“进一步编辑”是什么意思?(顺便说一句,在Linux上,O_RDONLY0...) - Andrew Henle

2

问题

这里的问题是被分配给file_des的文件描述符并非真正的1。

int test = dup(file_des);
fprintf(stderr, "%d", test);

3

现在,问题出在哪里呢?

问题在于您打开文件的方式。 O_CREAT 如果文件不存在则会创建一个文件。

没有规定您是要以读取、写入还是可读可写的方式打开文件。

由于您将文件与文件描述符 stdout 关联,因此您必须同时使用 O_WRONLY 标志。

int file_des = open(args[2],  O_CREAT | O_WRONLY,  0640);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接