1. 什么是进程?
- 进程就是运行中的程序,是系统资源分配的基本单位
- 每个进程都有唯一的PID(进程ID)
- 进程有父子关系,通过ps -ef可以查看
2. 进程的创建 - fork()
pid_t pid = fork();
- 简单理解:fork()就像细胞分裂,一个变两个
- 调用一次,返回两次:父进程得到子进程PID,子进程得到0
- 子进程是父进程的复制品
3. 进程的程序替换 - exec族
execl("/bin/ls", "ls", "-l", NULL);
- 保留进程ID,但内容完全变成新程序
- 就像换灵魂:外壳不变,内在全变
- 常用函数:execl, execlp, execle, execv, execvp等
4. 进程的等待与回收 - wait/waitpid
pid_t wait(int *status);
pid_t waitpid(pid_t pid, int *status, int options);
- 父进程等待子进程结束并回收资源
- 避免僵尸进程(zombie)的产生
- waitpid比wait更灵活,可以非阻塞等待
5. 进程的退出
exit(0); // 标准C库函数
_exit(0); // 系统调用
- exit会刷新缓冲区,exit直接退出
- 返回值0表示正常退出
一. 文件操作与I/O
1. 文件描述符
- 就像文件的"身份证号码"
- 标准输入(0)、标准输出(1)、标准错误(2)
- 每个进程最多可打开的文件数有限制
2. 文件操作基本函数
// 打开文件
int fd = open("test.txt", O_RDWR | O_CREAT, 0644);
// 读取文件
char buf[1024];
int n = read(fd, buf, sizeof(buf));
// 写入文件
write(fd, "hello", 5);
// 关闭文件
close(fd);
// 文件指针定位
lseek(fd, 0, SEEK_SET); // 回到文件开头
3. 文件属性获取
struct stat st;
stat("file.txt", &st);
- 获取文件大小:st.st_size
- 判断文件类型:S_ISREG(st.st_mode)、S_ISDIR(st.st_mode)
4. 目录操作
DIR *dir = opendir(".");
struct dirent *entry;
while ((entry = readdir(dir)) != NULL) {
printf("%s\n", entry->d_name);
}
closedir(dir);
三、进程间通信(IPC)
1. 管道通信
int fd[2];
pipe(fd); // fd[0]读端,fd[1]写端
- 单向通信:水管模型,一端进一端出
- 只能用于有亲缘关系的进程
- 适合简单的数据传输
2. 命名管道(FIFO)
// 创建命名管道
mkfifo("myfifo", 0644);
// 使用方法与普通文件类似
int fd = open("myfifo", O_WRONLY);
- 可用于无关进程间通信
- 遵循先进先出原则
3. 信号通信
// 信号处理函数
void sig_handler(int signo) {
printf("收到信号: %d\n", signo);
}
// 设置信号处理
signal(SIGINT, sig_handler);
- 常见信号:
- SIGINT (2): Ctrl+C中断
- SIGKILL (9): 强制终止(不可捕获)
- SIGTERM (15): 终止信号
- SIGCHLD (17): 子进程状态改变
- SIGALRM (14): 定时器到期
四、实用示例
1. 创建守护进程
void daemonize() {
pid_t pid = fork();
if (pid < 0) exit(1);
if (pid > 0) exit(0); // 父进程退出
setsid(); // 创建新会话
// 关闭标准输入输出错误
close(0);
close(1);
close(2);
// ...更多操作
}
2. 简单shell实现
while (1) {
printf("myshell> ");
fgets(cmd, sizeof(cmd), stdin);
if (fork() == 0) {
// 子进程执行命令
execlp(cmd, cmd, NULL);
exit(0);
} else {
// 父进程等待
wait(NULL);
}
}
五、常见错误与调试技巧
1. 经典错误
- 僵尸进程:子进程结束但未被回收
- 孤儿进程:父进程先于子进程结束
- 内存泄漏:申请的内存未释放
- 文件描述符泄漏:打开文件未关闭
2. 调试工具
- strace:跟踪系统调用
- gdb:代码调试器
- valgrind:内存错误检测
- lsof:查看打开的文件