#include "apue.h"
int glob = 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 */
glob++; /* modify variables */
var++;
} else {
sleep(2); /* parent */
}
printf("pid = %d, glob = %d, var = %d\n", getpid(), glob, var);
exit(0);
}
《Unix环境高级编程》真是一本经典,把之前学过的《编译原理》、《操作系统》和《C语言》这几本课的东西都复习了一遍,而且是有实实在在的代码在那里的,不像以前上课用的国内教材,讲得很抽象,听完后只记得概念,却不能动手操作。
例如上面这段代码就很让人玩味。
1. 第一个 语句printf("before fork\n"); 调用虽然出现在fork()的调用之前,但谁又会想到,Standard I/O 里一般都设有缓冲区的,这个 字符串 “before fork” 其实还没有被写到 stdout 标准输出里,这时就调用了fork(), 有了子进程,子进程就copy了一份与父进程同样的代码和数据,包括没有flush 的printf() 输出流在内,所以结果就输出了两次。
以Unix/Linux 的环境里,运行结果如下:
$ ./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
可以看到 before fork被输出了两次,子进程一次,父进程一次。
C语言里的细节真是多啊,各种设计的要注意的东西太多了!