目录
1.写在前面
2.关于环境
3.关于函数和操作
4.具体代码
2023年山东大学操作系统实验,第一次实验肥肠简单,压缩以后代码仅仅几行罢了
实验要求只是:创建一个父进程,然后创建子进程并且控制它每隔三秒输出一次当前目录下的文件(其实就是每隔三秒,让子进程完成一次ls -l操作)
这次试验主要是熟悉以下具体的操作,包括G系列的环境配置,在Linux环境下运行代码,进程相关的一些函数
(1)操作系统:Ubuntu22.04(受到沙袋某校园app维护组成员的pua,我直接把电脑的操作系统改成了Linux,所以8要问我怎么配虚拟机,不会啊qwq)
(2)代码运行环境:g++(gcc是c语言编译运行的环境,g++是cpp的) , 或者也可以为了省事,直接安装vscode,clion等
主要是还是对于一些函数的操作和解释
(1)先解释一下指令是怎么执行的
可执行文件名 参数1 参数2 参数3
可以发现大多数命令都是这样进行调用的,例如我们最常用的ll,其实原本为ls -l
其中ls就是可执行文件,完整的文件名应该是/bin/ls
(2)关于main函数中常用的两个参数
int main(int args,char * argv[]){
//函数体
}
这两个参数是啥玩意呢?这就要说我们的执行参数了
假设我们执行的时候(这个可执行文件叫main),执行指令是这样的
./main 1 2 3
这样在命令行窗口,我们就可以执行这个main文件(前提是存在这样一个可执行的文件,对于cpp文件我们最好编译一下,编译过程我们后面再说,而且不一定编译以后一定是cpp文件)
这样传入进来的时候,我们在函数体内读取args和argv,分别能独到的数值是
4 //这个代表我们有四个参数
参数一共是四个,是当前文件名+三个参数
["./main","1","2","3",null]
参数数组严格来说长度为5,真实长度为4,包括指令的全部
理论上来说,这个确实是没啥用,但是后面实验可能有更多要求,而且和后面的execve函数密切相关
(3)在g++的环境下如何编译文件并且执行(下个vscode就不麻烦了)
g++ 你要编译的文件 -o 编译后的文件名
./你要运行的文件名
(4)下面解释六个基本函数以及相关的内容(注意以下函数都是linux下有效的)
pid_t pid=fork();
fork函数是用来创建子进程的,子进程会根据父进程的副本进程创建,并且代码的执行范围是创建子进程开始,并且,返回的pid数值,如果为0,则代表当前的进程为子进程,如果为>0,则代表这是个父进程,<0代表进程创建失败,用这种方式来判断并且决定什么进程执行什么代码
(另外注意这个pid仅仅是一个识别号,并不是真正的进程号!!!!)
exit();
没啥好说的,立刻退出当前进程
kill(pid,notion);
向指定进程发送某种指令
execve(filename,arg[],env[])
perror("如果上述没执行成功,就会触发这一句,并且继续往下执行")
execve函数值得大书特书,因为这是一个系统调用的api,作用是改变当前进程接下来的执行内容
通俗来讲就是:不再执行下面的代码,转而执行指定的内容
实际作用上:相当于利用代码去在终端里执行一条指令
filename:是你要执行的文件名字(一定要可执行文件)
arg[]是个char* 类型的数组,他的组成为 文件名+参数+NULL
env也是类似的数组,组成为环境变量+NULL
(这两个数组必须以NULL结尾)
先举个栗子: 比如我们函数执行到一半,想要列出全部的文件内容 怎么办
首先我们知道,指令应该为 ls -l ,ls为可执行文件, -l为参数,在环境变量无所谓的情况下,我们的执行可以这样写
char * arg[]={"ls","-l",NULL};
char * env[]={NULL};
execve("ls",arg,env);
ok,有时候可以结合上面main函数中的隐藏函数来进行处理
./main ls -l
那么里面就可以写成
execve(argv[1],&argv[1],NULL)
//下面是几个无关痛痒的函数
int status;
pid_t pid=wait(&status);
wait函数其实是一个阻塞方法,在父进程中使用,等待子进程完成以后,会把结束状态压入status中,并且返回这个wait函数对应的进程号.
每一个wait函数都会对应一个子进程,其中返回值大于0代表子进程结束
其他的返回值有不同的含义,详见文档
另外还有一个衍生的函数
waitpid(pid, status,opions)
pid是指定等待某个进程完成任务,而不是像wait一样按照子进程的顺序(注意pid=-1的时候有个等待集合的概念,这个要注意)
status是结束状态,以何种状态结束
options是默认行为,比如没有终止就立刻返回,里面有一些内置的常量
getpid()
getppid()
获取当前进程号,获取父进程号
sleep();
指定线程休眠多少秒
#include
using namespace std;
int main(int args,char * arg[]){
for(int i=0;i<5;i++){
pid_t pid=fork();
if(pid==0){
char * args[]={"/bin/ls","-l",NULL}; char * envp[]={NULL};
execve("/bin/ls",args,envp);
}else if(pid<0)
cout<<"err!!!"<
在vscode中点击运行即可,参数已经内置