Linux write与printf,strlen与sizeof

2020-06-30  本文已影响0人  打出了枫采

注意到此二者的差异源于《Unix环境高级编程》一书8.3章节fork function。

示例程序

注意自行验证时,应注释掉apue.h包含,自行实现err_sys函数,以及包含缺乏的头文件,即可编译过。下面是经过书中示例修改后的代码,linux下可以编译运行

//#include "apue.h"
#include "unistd.h"

void err_sys(char * errinfo)
{
    printf("Error: %s\n", errinfo);
    exit(-1);
}

int globvar = 6; /* external variable in initialized data */
char buf[] = "a write to stdout\n";
int main(void)
{
    int var; /* automatic variable on the stack */
    pid_t pid;
    var = 88;
    if (write(STDOUT_FILENO, buf, sizeof(buf)-1) != sizeof(buf)-1)
        err_sys("write error");
    printf("before fork\n"); /* we don’t flush stdout */
    
    if ((pid = fork()) < 0) {
        err_sys("fork error");
    } else if (pid == 0) { /* child */
        globvar++; /* modify variables */
        var++;
    } else {
        sleep(2); /* parent */
    }
    
    printf("pid = %ld, glob = %d, var = %d\n", (long)getpid(), globvar,var);
    exit(0);
}

程序运行结果 前者为直接运行的打印结果,后者为程序输出重定向到文件后的运行打印结果:

$./a.out
a write to stdout
before fork
pid = 430, glob = 7, var = 89  #child’s variables were changed
pid = 429, glob = 6, var = 88  #parent’s copy was not changed
$ ./a.out > temp.out
$ cat temp.out
a write to stdout
before fork
pid = 432, glob = 7, var = 89
before fork
pid = 431, glob = 6, var = 88

sizeof与strlen

When we write to standard output, we subtract 1 from the size of buf to avoid
writing the terminating null byte. Although strlen will calculate the length of a string
not including the terminating null byte, sizeof calculates the size of the buffer, which
does include the terminating null byte. Another difference is that using strlen
requires a function call, whereas sizeof calculates the buffer length at compile time, as
the buffer is initialized with a known string and its size is fixed.

示例程序中write函数写入字符串时计算长度使用的是sizeof,并且减去1,去掉字符串末尾的空字符,避免write函数写空字符(相当于没有写入内容);实际也可以直接使用strlen(buf),等价于sizeof(buf) -1。

write 与 printf

the write function is not buffered. Because write is called
before the fork, its data is written once to standard output. The standard I/O library,
however, is buffered.standard output is line buffered if it’s
connected to a terminal device; otherwise, it’s fully buffered.
When we run the
program interactively, we get only a single copy of the first printf line, because the
standard output buffer is flushed by the newline. When we redirect standard output to
a file, however, we get two copies of the printf line. In this second case, the printf
before the fork is called once, but the line remains in the buffer when fork is called.
This buffer is then copied into the child when the parent’s data space is copied to the
child. Both the parent and the child now have a standard I/O buffer with this line in it.
The second printf, right before the exit, just appends its data to the existing buffer.
When each process terminates, its copy of the buffer is finally flushed
上一篇 下一篇

猜你喜欢

热点阅读