课程设计开始了,实验很有意思,写博客总结学到的知识
白嫖容易,创作不易,学到东西才是真
本文原创,创作不易,转载请注明!!!
本文链接
个人博客:https://ronglin.fun/archives/173
PDF链接:见博客网站
CSDN: https://blog.csdn.net/RongLin02/article/details/118308366
为了美观,实验源代码在结尾处,整合版见下
链接:https://pan.baidu.com/s/1rXj1QJGuw-BVc5sQWret9w
提取码:Lin2
操作系统课程设计源代码
本次操作系统课程设计合集
操作系统课设之Windows 进程管理
操作系统课设之Linux 进程管理
操作系统课设之Linux 进程间通信
操作系统课设之Windows 的互斥与同步
操作系统课设之内存管理
操作系统课设之虚拟内存页面置换算法的模拟与实现
操作系统课设之基于信号量机制的并发程序设计
操作系统课设之简单 shell 命令行解释器的设计与实现
仅用于学习,如有侵权,请联系我删除
Linux 进程管理
通过进程的创建、撤销和运行加深对进程概念和进程并发执行的理解,明确进程和程序之间的区别。
学习背景知识,了解Linux下的创建进程的方法。
由于操作系统的平时作业也是用Linux,再加上布置过在Linux下的C语言编程的作业,所以本验证性实验完成较为轻松
Linux环境:
虚拟机:Ubuntu 18.04 LTS;硬盘100G;内存4G;64位;4核心
Linux内核:5.11.8 开发工具:CodeBlocks
Linux虚拟机的安装可以看我这两篇博客:
https://blog.csdn.net/RongLin02/article/details/114273129
https://blog.csdn.net/RongLin02/article/details/115419994
原理:
主要涉及到两个函数,一个是fork(),一个是exec()系列函数
fork 会建立一个子进程,父进程继续运行,子进程在同样的位置执行同样的程序。fork()会分别返回两个值给父子进程,fork()返回子进程的 pid给父进程,fork()返回 0给子进程。出错时返回-1。 exec()函数会创建一个新的进程映象置换当前的进程映象。exec函数族的作用是根据指定的文件名找到可执行文件,并用它来取代调用进程的内容,换句话说,就是在调用进程内部执行一个可执行文件。这里的可执行文件既可以是二进制文件,也可以是任何Linux下可执行的脚本文件
在操作系统的平时作业中,我还用到了vfork()函数。因为fork()创建的子进程其实是父进程数据的copy,也就是说父子进程的数据并不是共享的,子进程只是父进程的翻版,类似于c语言函数中的传递形式参数,要想数据共享,其实也有很多方法,有些资料书上提到很多CLONE_开头的标志位就是控制哪些东西是父子进程共享的。不过有更简单的vfork()函数,其实本质上是一样的,都是调用内核函数do_fork()。需要注意的是,不论多进程还是多线程,数据一旦共享,会涉及到安全问题,不过vfork()创建子进程之后,父进程就会阻塞,所以就没安全问题了。
本验证实验不涉及到父子进程的数据传递
在Ubuntu下安装好CodeBlocks,然后用CodeBlocks,创建一个新工程,将指导书的代码copy到main.c文件中,然后编译运行查看结果
多次运行,查看结果
关键代码
int x;
srand((unsigned)time(NULL));
while((x=fork())==-1);
if (x==0)
{
sleep(rand() % 2);
printf("a");
}
else
{
sleep(rand() % 3);
printf("b");
}
printf("c");
新建一个工程,将实例代码copy到main.c下
运行查看结果
关键代码
pid_t pid;
/* fork a child process */
pid = fork();
if (pid < 0)
{
/* error occurred */
fprintf(stderr, "Fork Failed");
return 1;
}
else if (pid == 0)
{
/* 子进程 */
execlp("/bin/ls","ls",NULL);
}
else /* 父进程 */
{
/* 父进程将一直等待,直到子进程运行完毕*/
wait(NULL);
printf("Child Complete\n");
}
这是几次的运行的结果。
分析结果:
子进程输出a和c,父进程输出b和c,当fork()成功之后,将父进程的代码copy一份给子进程运行,所以说父子进程都会输出c,但是控制台只有一个,父子进程会抢输出,再加上一个随机睡眠函数,所以就会出现不同的输出结果。
运行结果
子进程会执行execlp()调用ls命令,输出当前的目录结构,同时父进程因为用了wait(null),会自我阻塞,等待随机一个进程结束,然后再执行。
Wait函数也有两个,一个是wait(),另一个是waitpid(),后者比前者功能更强大。
由于操作系统平时作业的关系,我对于Linux系统也比较熟悉了,在Linux系统下的C/C++编程也比较熟悉,故完成本验证实验也很轻松。
平时作业我们曾完成过,Linux虚拟环境的安装,Linux内核的编译,Linux下的C语言的进程与线程编程,Linux下打印进程树。
这些在我的博客主页中都可以搜到
=w=
#include
#include
#include
#include
int main()
{
int x;
srand((unsigned)time(NULL));
while((x=fork())==-1);
if (x==0)
{
sleep(rand() % 2);
printf("a");
}
else
{
sleep(rand() % 3);
printf("b");
}
printf("c");
return 0;
}
#include
#include
#include
#include
int main()
{
pid_t pid;
/* fork a child process */
pid = fork();
if (pid < 0)
{
/* error occurred */
fprintf(stderr, "Fork Failed");
return 1;
}
else if (pid == 0)
{
/* 子进程 */
execlp("/bin/ls","ls",NULL);
}
else /* 父进程 */
{
/* 父进程将一直等待,直到子进程运行完毕*/
wait(NULL);
printf("Child Complete\n");
}
return 0;
}