"本文档是关于UNIX环境高级编程的知识介绍,涵盖了fork函数的使用、进程创建以及文件I/O等多个核心概念。"
在UNIX操作系统中,`fork()`函数是创建新进程的关键方法。这个函数允许一个已存在的进程创建它的副本,即子进程。当调用`fork()`时,内核会为子进程分配资源,并复制父进程的数据空间、堆和栈。然而,父子进程并不共享这些内存区域,除非是只读的代码段,它们可能会被共享。在很多现代实现中,为了提高效率,采用写时复制(Copy-On-Write, COW)技术,避免不必要的数据拷贝,直到某个进程尝试修改这些区域。
`fork()`函数调用后会返回两次,分别在父进程和子进程中。在子进程中返回值为0,而在父进程中返回值是新创建子进程的进程ID。这样设计是因为一个进程可能有多个子进程,但每个子进程只有一个父进程。子进程可以通过`getppid()`获取其父进程的ID,而进程ID为0通常代表交换进程。
以下是一个`fork()`函数的简单示例程序(程序8-1):
```c
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main() {
int var = 88;
printf("before fork\n");
pid_t pid = fork();
if (pid == 0) { // 子进程
var = 89;
printf("pid = %d, glob = %d, var = %d\n", getpid(), 7, var);
} else if (pid > 0) { // 父进程
sleep(2); // 父进程等待2秒
printf("pid = %d, glob = %d, var = %d\n", getpid(), 6, var);
} else { // 错误情况
printf("fork failed\n");
return 1;
}
return 0;
}
```
在这个例子中,`fork()`之后,父子进程可能会交错执行,具体顺序依赖于内核调度。如果需要父子进程间的同步,就需要使用进程间通信机制,如信号或管道等。
此外,文档还涉及到了UNIX的基础知识,如文件和目录管理、输入输出、进程控制、用户标识、信号处理、时间值、系统调用与库函数等。UNIX标准化部分介绍了ANSI C、IEEE POSIX、X/Open XPG3和FIPS 151-1等相关标准及其在不同UNIX实现中的差异。文件I/O部分详细讨论了`open()`, `creat()`, `close()`, `lseek()`, `read()`, `write()`等函数的使用,以及文件共享、原子操作和I/O效率等问题。
这份资料深入浅出地讲解了UNIX环境下的高级编程技术,包括进程创建、文件操作等核心概念,对于理解和掌握UNIX系统编程具有很高的价值。