操作系统1

实验3.3 Shell编程实验(进程管理实验)

1、实验目的

通过编写shell程序,了解子进程的创建和父进程与子进程间的协同,获得多进程程序的编程经验。

2、实验内容1

设计一个简单的shell解释程序,能实现基本的bsh功能。

3、实验原理

将每一条命令分子段压入argv栈。然后再子进程中调用execvp()来实现该命令的功能。

4、代码(源代码清单)

#include <stdio.h>

#include <string.h>

#include <stdlib.h>

#define BUFFERSIZE 256

//最简单的shell,只是简单的执行命令调用,没有任何的其他功能

int main()

{

char buf[BUFFERSIZE],*cmd,*argv[100];

char inchar;

int n,sv,buflength;

int result;

buflength = 0;

for(;;) {

printf("=> ");

//处理过长的命令;

inchar = getchar();//读取命令

while (inchar != '\n' && buflength < BUFFERSIZE ){

buf[buflength++] = inchar;

inchar = getchar();

}

if (buflength > BUFFERSIZE){

printf("Command too long,please enter again!\n");

buflength = 0;

continue;

}

else

buf[buflength] = '\0';

//解析命令行,分成一个个的标记

//char *strtok(char *s,char *delim)

//分解字符串为一组字符串。s为要分解的字符串,delim为分隔符字符串。

cmd=strtok(buf," \t\n");

if(cmd) {

if(strcmp(cmd,"exit")==0) exit(0);

n=0;

argv[n++]=cmd;

while(argv[n++]=strtok(NULL," \t\n"));

if(fork()==0) {

execvp(cmd,argv);

fprintf(stderr,"sxh:%s:command not found.\n",buf);//如果子进程顺利执行,这段话是不会执行的

exit(1);

}

wait(&sv);

buflength = 0;

}

}

}

实验内容2

编写一个带有重定向和管道功能的Shell

1.设计思路

通过fork()创建子进程,用execvp()更改子进程代码,用wait()等待子进程结束。这三个系统调用可以很好地创建多进程。另一方面,编写的Shell要实现管道功能,需要用pipe()创建管道使子进程进行通信。

2.源代码清单

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <fcntl.h>

#define BUFFERSIZE256

//具有输入输出重定向的功能 和管道功能

int

main()

{

char buf[256],*buf2,*cmd,*cmd2,*argv[64],*argv2[64],*infile,*outfile;

char inchar;

int n,sv,buflength,fd[2];

for(;;) {

buflength = 0;

printf("=> ");

inchar = getchar();

while (inchar != '\n' && buflength < BUFFERSIZE ){

buf[buflength++] = inchar;

inchar = getchar();

}

if (buflength > BUFFERSIZE){

fprintf(stderr,"Command too long,please enter again!\n");

buflength = 0;

continue;

}

else

buf[buflength] = '\0';

//检查是否具有管道操作符

//strstr()在字符串中查找指定字符串的第一次出现,buf2指向管道符号前端的命令

buf2=strstr(buf,"|");

if(buf2)

*buf2++='\0';

else {

//否则查看是否具有重定向的操作符

infile=strstr(buf,"<");

outfile=strstr(buf,">");

if(infile) {

*infile='\0';

infile=strtok(infile+1," \t\n");

}

if(outfile) {

*outfile='\0';

outfile=strtok(outfile+1," \t\n");

}

}

//解析命令行,分成一个个的标记

cmd=strtok(buf," \t\n");

//执行管道命令

if(buf2){

if(strcmp(cmd,"exit")==0) exit(0);

if(!cmd) {

fprintf(stderr,"Command token error.\n");

exit(1);

}

n=0;

//管道后端的命令

argv[n++]=cmd;

while(argv[n++]=strtok(NULL," \t\n"));

//管道前端的命令

cmd2=strtok(buf2," \t\n");

if(!cmd2) {

fprintf(stderr,"Command token error.\n");

exit(1);

}

n=0;

argv2[n++]=cmd2;

while(argv2[n++]=strtok(NULL," \t\n"));

pipe(fd);

if(fork()==0) {

dup2(fd[0],0); //dup2 复制文件句柄,将fd[0]复制到描述符0。

close(fd[0]); close(fd[1]);

execvp(cmd2,argv2);

fprintf(stderr,"** bad command\n"); exit(1);

} else if(fork()==0) {

dup2(fd[1],1);

close(fd[0]);close(fd[1]);

execvp(cmd,argv);

fprintf(stderr,"** bad command\n"); exit(1);

}

close(fd[0]);

close(fd[1]);

wait(&sv);

wait(&sv);

buflength = 0;

}

//如果没有管道命令,如果有重定向就执行重定向操作,如果没有重定向就当作普通shell命令执行

else{

if(cmd) {

if(strcmp(cmd,"exit")==0) exit(0);

n=0;

argv[n++]=cmd;

while(argv[n++]=strtok(NULL," \t\n"));

if(fork()==0) {

int fd0=-1,fd1=-1;

if(infile) fd0=open(infile,O_RDONLY);

if(outfile) fd1=open(outfile,O_CREAT|O_WRONLY,0666);

if(fd0!=-1) dup2(fd0,0);//dup2 复制文件句柄,将fd0复制到描述符0。

if(fd1!=-1) dup2(fd1,1);//dup2 复制文件句柄,将fd1复制到描述符1。

close(fd0);

close(fd1);

execvp(cmd,argv);

fprintf(stderr,"** Bad command\n");

exit(1);

}

wait(&sv);

buflength = 0;

}

}

}//for  

}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值