我的C类包含一个非常小的shell.
我们的shell检查用户的输入行是否有内部命令(如cd或exit),如果没有找到,则forks()和execs()输入行.
我希望实现一个万无一失的分叉(这超出了本课程的职责范围,请不要让我做自己的功课,这更多的是个人研究,以了解更多的linux'内部) .我目前的做法是:
t = fork();
if (t < 0) {
if (errno == ENOSYS) {
printf("fork() is not supported on this platform. Minishell will not work.");
break;
}
else if (errno == ENOMEM) {
printf("No free kernel memory. Minishell will exit.");
break;
}
else {
int try = 0;
while (t < 0 && try < 10) {
try++;
t = fork();
}
}
continue;
}
Run Code Online (Sandbox Code Playgroud)
我的理解是ENOSYS不允许分叉,因此我们退出,ENOMEM表示内核内存故障 - 超过我的薪水(我没有报酬,我是学生;)),因此我们也退出.保持EAGAIN有两种风格,这两种风格都可以通过等待和再次调用fork()来解决.
在之前的练习中,我们已经启动了一万个叉子,如果我没记错的话,大约1500个失败了,直到我们实现了一个类似于我的计数器.如果我想以一种不那么天真的方式实现这个东西,我该怎么办?我想,特别是硬编码的十次尝试有点愚蠢.
谢谢.
我认为你当前的重试方法是误解了fork的EAGAIN错误的含义.从Linux手册页:
EAGAIN fork()无法分配足够的内存来复制父页面表并为子节点分配任务结构.
EAGAIN由于遇到调用者的RLIMIT_NPROC资源限制,因此无法创建新进程.要超过此限制,进程必须具有CAP_SYS_ADMIN或CAP_SYS_RESOURCE功能.
第一个与ENOMEM相当,第二个是达到流程上限的问题.除非你期望你的minishell让孩子一直处于死亡状态,否则连续尝试10次可能无能为力.
我建议你的EAGAIN也是你的fork代码的致命错误.
但是,如果您的程序可以执行某些操作来缓解内存压力(释放程序缓存等),则可以执行此操作并再次尝试一次.
值得一提的是,在正常负载下,任何现代系统几乎都不存在使得fork失败的条件.