上机作业4 : Shell管道和重定向功能的实现

上机作业4 : Shell管道和重定向功能的实现

1 实验要求

使用fork(), exec(), dup2(), pipe() ,open(),wait()等系统调用编写C语言程序完成与下列shell命令等价的功能。
grep -v usr < /etc/passwd | wc –l > r.txt; cat r.txt
(提示:为简化编程,不需要用strtok断词,直接用execlp实现能达到shell命令相同功能的程序即可)
例如:execlp(“grep”, “grep”, “-v”, “usr”, 0);

2 实验过程

2.1 命令分析

grep -v usr < /etc/passwd

/etc/passwd作为重定向输入,查找不含有usr字段的行

wc –l > r.txt

统计输入文本的行数,并通过输出重定向到r.txt中,此时第一步的输出通过管道机制传入

cat r.txt 

获取文件r.txt的内容并输出到屏幕上

2.2 函数设计

2.2.1 pipe()

pipe[fd]用于创建管道,申请数组fd[2],其中fd[0]进行读操作,fd[1]进行写操作

2.2.2 fork()

fork用于创建进程,在这里用于执行各条指令

2.2.3 dup2()

dup2()用来复制文件描述符,可以将文件保存到磁盘中

2.2.4 execlp()

用一个指定的程序文件,重新初始化一个进程,可指定新的命令行参数

其中execlp的系统调用格式为:

execlp(char *file,char *arg0,char *arg1,...,0);
2.2.5 wait()

等待进程的子进程终止,其中wait(&sv)中的sv保存子进程终止的原因

2.2.6 open()

用于打开或创建一个文件

2.3 程序设计

2.3.1 grep指令
if (fork() == 0) //子进程,进行grep指令的执行
    {
        dup2(open("/etc/passwd",O_RDONLY), 0);  
        dup2(fd[1], 1); //复制文件描述符,将文件存到磁盘文件中
        close(fd[0]);
        execlp("grep", "grep", "-v", "usr", NULL);
    }

/etc/passwd中的内容以文件形式传入,进行读写操作,最后分析grep指令

2.3.2 wc指令
if (fork() == 0) //子进程,进行wc指令的执行
    {
        dup2(fd[0], 0);
        dup2(open("r.txt", O_RDWR | O_CREAT,S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH), 1);
        close(fd[1]);
        execlp("wc", "wc", "-l", NULL);
    }

wc指令需要输出重定向到r.txt文件中,因此此处调用open()函数,使用完后关闭管道

2.3.3 cat指令
if (fork() == 0) //子进程,进行cat指令的执行
    {
        execlp("cat", "cat", "r.txt", NULL);
    }
2.3.4 wait()函数使用

每当创建一个子进程时,使用wait()函数来对子进程进行销毁与回收,因此此处调用三次wait函数

3 实验结果

3.1 Linux指令运行如下:

在这里插入图片描述

3.2 Shell.c指令运行如下:

在这里插入图片描述

4 实验感想

​ 通过本次试验,加深了我对Linux管道、重定向功能的认识,以及如何使用c语言提供的系统调用函数来实现管道、重定向等机制,也提高了我的编程能力

5 源代码

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/wait.h>
grep -v usr < /etc/passwd | wc –l > r.txt; cat r.txt 
int main(void)
{
    int sv, fd[2];
    pipe(fd);  //创建管道,fd[0]用于读操作,fd[1]用于写操作
    if (fork() == 0) //子进程,进行grep指令的执行
    {
        dup2(open("/etc/passwd",O_RDONLY), 0);  
        dup2(fd[1], 1); //复制文件描述符,将文件存到磁盘文件中,管道的写端代替终端
        close(fd[0]);
        execlp("grep", "grep", "-v", "usr", NULL);
    }
    if (fork() == 0) //子进程,进行wc指令的执行
    {
        dup2(fd[0], 0); //从管道里获取数据
        dup2(open("r.txt", O_RDWR | O_CREAT,S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH), 1);
        close(fd[1]);
        execlp("wc", "wc", "-l", NULL);
    }
    close(fd[1]); //父进程关闭
    close(fd[0]);
    wait(&sv);
    wait(&sv);
    if (fork() == 0) //子进程,进行cat指令的执行
    {
        execlp("cat", "cat", "r.txt", NULL);
    }
    wait(&sv);
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值