记录于2022.7.7——南林操作系统课设心得体会
<任务>
编写一段程序,使用系统调用fork()创建两个子进程。当此程序运行时,在系统中有一个父进程和两个子进程活动。让每一个进程在屏幕上显示一个字符,试观察记录屏幕上的显示结果,并分析原因。修改已编好的程序,将每个进程的输出由单个字符改为一句话。
显示一个字符:
#include <iostream>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
int main(int argc, char* argv[]) {
pid_t pid1, pid2; // 记录fork()返回的值
/*
fork()返回值:
(1) 在父进程中,fork返回新创建子进程的进程ID
(2) 在子进程中,fork返回0
(3) 如果出现错误,fork返回一个负值
*/
while ((pid1 = fork()) == -1); // 创建子进程1
if (pid1 == 0) { // 如果是在子进程1中
std::cout << "1" << std::endl;
}
else {
while ((pid2 = fork()) == -1);
if (pid2 == 0) { // 如果是在子进程2中
std::cout << "2" << std::endl;
}
else { // 如果是在父进程中
std::cout << "F" << std::endl;
// 等待子进程结束
wait(NULL);
wait(NULL);
}
}
return 0;
}
结果:
分析:输出结果为“F12”,其中“F”是父进程的输出,“1”是第一个子进程的输出,“2”是第二个子进程的输出。该运行结果是在CentOS 7上运行后得到的,该操作系统采用的进程调度策略为CFS算法,由于此时每个进程只打印一个字符,当执行到pid1 = fork()时,创建子进程1,此时父进程的虚拟运行时间小于子进程1,执行父进程,当执行到pid2 = fork()时,创建子进程2,此时父进程的虚拟运行时间小于子进程2,执行父进程,打印字符“F”,然后父进程执行wait()函数,进入阻塞状态,等待子进程执行完毕,在此案例中,子进程1的虚拟运行时间小于子进程2的虚拟运行时间,执行子进程1,打印字符“1”,待子进程1执行完毕后,父进程由阻塞状态变为就绪状态,此时,若操作系统根据调度算法将处理机分配给父进程,父进程执行第二个wait()函数,进入阻塞状态,调度算法将处理机分配给子进程2,打印字符“2”,然后子进程2执行完毕,父进程由阻塞状态变为就绪状态,获得处理机,父进程随之执行完毕。
显示一句话:
#include <iostream>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
int main(int argc, char* argv[]) {
pid_t pid1, pid2; // 记录fork()返回的值
/*
fork()返回值:
(1) 在父进程中,fork返回新创建子进程的进程ID
(2) 在子进程中,fork返回0
(3) 如果出现错误,fork返回一个负值
*/
while ((pid1 = fork()) == -1); // 创建子进程1
if (pid1 == 0) { // 如果是在子进程1中
std::cout << "pid1: " << getpid() << std::endl;
}
else {
while ((pid2 = fork()) == -1);
if (pid2 == 0) { // 如果是在子进程2中
std::cout << "pid2: " << getpid() << std::endl;
}
else { // 如果是在父进程中
std::cout << "fpid: " << getpid() << std::endl;
// 等待子进程结束
wait(NULL);
wait(NULL);
}
}
return 0;
}
结果:
分析:输出结果与输出单个字符时一样,父进程先执行输出语句,随后执行wait()函数进入阻塞状态,然后由调度算法将处理机分配给子进程1,子进程1执行输出语句,随后子进程1执行完毕,父进程由阻塞变为就绪状态,并获得处理机,再一次执行wait()语句,进入阻塞状态,然后调度程序将处理机分配给子进程2,子进程2执行输出语句,随后执行完毕,父进程此时由阻塞变为就绪状态,然后获得处理机,随后父进程执行完毕。
注意,linux采用的进程调度策略为CFS算法,感兴趣的朋友可以了解一下该算法,并根据运行结果来分析该算法。