这段代码展示了一个父子进程之间的基本文件读写操作,并使用信号量(sem)来进行同步。以下是对代码的一些重要部分的解析和说明:
代码功能
- 创建文件: 父进程创建并打开一个名为
test.txt
的文件,准备进行写入。 - 父子进程创建: 通过调用
fork()
创建一个子进程。 - 信号量: 使用信号量进行进程间同步,以避免在读取或写入文件时出现数据竞争。
- 父进程输入: 父进程提示用户输入字符串,并将其写入文件中。
- 子进程读取: 子进程等待一秒后,读取该文件内容并打印到标准输出。
注意事项
- 错误处理: 本代码没有包括足够的错误处理,实际应用中应该检查系统调用是否成功(例如,
open
,fork
,read
,write
)。 gets
函数使用: 不建议使用gets
函数,因为它不安全,会导致缓冲区溢出。可以改用fgets(str, sizeof(str), stdin)
来获取用户输入。- 信号量实现 (
sem_p
,sem_v
): 需要有对应的信号量实现,这里假定你已经实现了这些函数用于加锁和解锁。 - 资源清理: 确保在程序结束前关闭所有打开的文件描述符和移除信号量。
示例改良
这里提供一个稍微改良的版本:
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/wait.h>
#include <string.h>
#include "sem_pv.h"
int main(void)
{
key_t key;
int pid, fd, semid, n;
char str[80];
// 获取唯一键值
key = ftok(".", 5);
// 初始化信号量
semid = sem_init(key);
// 打开/创建文件 test.txt
fd = open("test.txt", O_RDWR | O_CREAT | O_TRUNC, 0644);
if (fd == -1) {
perror("Error opening file");
return 1;
}
while ((pid = fork()) == -1); /* 重复尝试直到成功 */
if (pid == 0) /* 子进程 */
{
sleep(1); // 确保父进程先运行
sem_p(semid); // P 操作
lseek(fd, SEEK_SET, 0);
read(fd, str, sizeof(str));
sem_v(semid); // V 操作
printf("child: read str from test file: %s\n", str);
exit(0);
}
else /* 父进程 */
{
sem_p(semid); // P 操作
printf("parent: please enter a string for the test file (strlen<80):\n");
fgets(str, sizeof(str), stdin); // 用 fgets 替代 gets 防止溢出
n = strlen(str);
lseek(fd, SEEK_SET, 0);
write(fd, str, n);
sem_v(semid); // V 操作
wait(NULL); // 等待子进程结束
close(fd); // 关闭文件描述符
sem_rmv(semid); // 移除信号量
exit(0);
}
}
以上是对原始代码的一些分析与改良示例,希望能帮助你更好地理解和使用此类多进程编程模式。
内容由零声教学AI助手提供,问题来源于学员提问