此lab应该为学校自己留的lab作业,此处仅把本菜鸡的代码思路展示作为参考,欢迎大家完善!!
-
一、实验准备
1.学习ps、pstree和kill等命令的使用方法。能通过ps命令查看进程号、可执行文件名(命令)、运行状态信息;能通过pstree查看系统进程树;能利用kill命令根据进程号(pid)杀死进程。
2. 在主目录创建李华-12345678(姓名-学号)文件夹,并在该文件夹创建lab6文件,编写以下代码并保存为1.c。(该代码产生两个进程,并且通过getchar()进行阻塞)
#include<stdio.h>
#include<unistd.h>
int main()
{
pid_t pid=fork();
if(pid<0) printf("error!");
else if(pid==0) getchar();
else getchar();
return 0;
}
然后使用命令gcc 1.c -o hello进行编译,通过命令./hello &执行(&表示后台执行,运行后会出现父进程pid),利用hello文件掌握ps、pstree和kill等命令
命令实例:
./hello &
ps
pstree -p (此处填pid号)
kill -kill (此处填pid号)
二、在lab6文件夹里面编写代码,创建6个子进程,并保存为2.c
此处只需循环创建6个子进程即可。
#include<stdio.h>
#include<unistd.h>
int main()
{
for(int i=0;i<6;i++)
{
pid_t pid =fork();
if(pid<0) printf("error!");
if(pid==0) break;
if(pid>0) continue;
}
getchar();
return 0;
}
指令示例:
gcc 2.c -o 2.1
./2.1 &
pstree -p (此处填Pid号)
最后别忘了kill,方便后续实验ps
三、编写3.c,实现6层子进程嵌套(使用getchar作为阻塞,子进程会被kill且ps只能显示2个进程,此处选用pause阻塞)
此处子进程完成链式嵌套即可。
此处还需说明一下,有同学可能没理解标题的意思,实际是前两个文件都用getchar()进行阻塞,但这里不行,需要把getchar()改为pause()才行(可以实践一下发现确实不行)
#include<stdio.h>
#include<unistd.h>
int main()
{
for(int i=0;i<6;i++)
{
pid_t pid =fork();
if(pid<0) printf("error!");
if(pid>0) break;
if(pid==0) continue;
}
pause();
return 0;
}
指令示例:
gcc 3.c -o 3.1
./3.1 &
ps
pstree -p (此处填Pid号)
最后别忘了kill,方便后续实验ps
四、编写4.c,实现一个父进程下面3个子进程,一个子进程下面3个进程。
此处需要父进程循环创建子进程,然后每个子进程循环创建子进程,注意循环条件即可
#include<stdio.h>
#include<unistd.h>
int main()
{
for(int i=0;i<3;i++)
{
pid_t pid =fork();
if(pid<0) printf("error!");
if(pid==0)
{
for(int i=0;i<3;i++)
{
pid_t pid1=fork();
if(pid<0) printf("error!");
if(pid==0) break;
if(pid>0) continue;
}
pause();
}
if(pid>0) continue;
}
pause();
return 0;
}
指令示例:
gcc 4.c -o 4.1
./4.1 &
pstree -p (此处填Pid号)
最后别忘了kill,方便后续实验ps
五、编写5.c,实现父进程与子进程交替输出10次,父进程输出word pid,子进程输出 hello pid。
此处代码实现我感觉可以有多种写法,大家可以自己尝试一下,此处仅对课程实验要求更接近的写法来完成。
思路:
父进程循环创建子进程,由于无法确定哪个进程优先运行,所以需要父进程wait子进程。
PS:此处代码是我最初写的,部分地方可以优化修改,欢迎大家尝试!
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/wait.h>
int main()
{
int status;
for(int i=0;i<10;i++)
{
pid_t pid =fork();
if(pid<0) printf("error!");
if(pid==0)
{
pid=getpid();
printf("hello %d\n",pid);
exit(0);
}
if(pid>0)
{ if(waitpid(-1,&status,0)>0)
pid=getpid();
printf("world %d\n",pid);
continue;
}
}
pause();
return 0;
}
gcc 5.c -o 5.1
./5.1 &
最后别忘了kill,方便后续实验ps
六、自定义shell
尝试自行设计一个C语言小程序,完成基本的shell功能
要求:给出命令行提示符,能够逐次接收命令;对于命令分三种,内部命令(实现help命令给出用法,exit命令退出shell,xuehao命令输出自己自己的学号)、外部命令(磁盘上的可执行文件)以及无效命令(不是上述2种命令)。
emmm,对于本人来说最后一个实验难度有点大,外部命令只实现了ls 和 ./,都是实验模板所涉及的,也欢迎大家在我的代码基础上修改完善,实现更多功能!
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/wait.h>
#include <string.h>
#include <sys/types.h>
char* command_argV[50];
char str2[6];
void eval(char *cmdline)
{
pid_t pid=fork() ;
if(pid==0){
if(strcmp(cmdline,"help")==0)
{
printf("---------\n内部命令 :\nhelp :打印帮助信息\nxuehao :打印学号\nexit :退出\n---------\n外部命令:\nexec +命令\n---------");
}
else if(strcmp(cmdline,"xuehao")==0)
{
printf("学号: 8888888888");
}
else if(strcmp(str2,"exec")==0)
{
command_argV[0] = strtok(cmdline, " ");
int index = 1;
while(command_argV[index++] = strtok(NULL, " "));
if(strcmp(command_argV[1],"ls")==0)
execl("/bin/ls",command_argV[1] ,NULL);
else execvp(command_argV[1],command_argV);
}
else printf("无效命令");
exit(0);
}
int status = 0;
if(pid>0)
waitpid(-1, &status, 0);
}
int main()
{
printf("welcome to my shell!");
char cmdline[50];
while(1)
{
memset(cmdline,'\0',sizeof(cmdline));
printf("\nshell>");
fgets(cmdline,50,stdin);
cmdline[strlen(cmdline) - 1] = '\0';
memset(str2,'\0',sizeof(str2));
strncpy(str2, cmdline, 4);
str2[4] = '\0';
if(strcmp(cmdline,"exit")==0)
{ printf("结束shell ,bye!");
exit(0);
}
eval(cmdline);
}
}
指令示例:
gcc myshell.c -o myshell (此处根据自己命名来写就好)
./myshell
ads
help
xuehao
exec ls
exec ./5.1
七、小结
以上本实验就完成了,由于是学校自己编的,所以网上没有很完美的,我就自己写了一篇供大家参考,欢迎大家修改我的代码并提出建议!!