在Linux里面有三个标准流 :标准输入0,标准输出1,标准错误2

0,1,2对应的物理设备一般是 : 键盘、显示器、显示器


通过上图我们看到原本应该输出到显示器上的内容,输出到了文件myfile中,这种现象叫做输出重定向。常见的重定向有>,>>,<  即输出重定向,输出附加定输入向符,输入重定向

                                        1.输出重定向
>>1.概念

    把命令的标准输出重定向到指定文件中

>>2.格式
命令>文件名

命令>>文件名

说明: 输出附加定向符( >> )的作用是把命令/程序的输出附加到指定文件的末尾

例子:who>userlog

        date>>userlog

>>3.自己实现重定向

运行结果:


                                        2.输入重定向
>>1.概念

    让命令从指定文件中取得输入数据

>>2.格式
命令<文件名
例子: bash<ex1   //从脚本文件ex1中取得命令
         wc<file    //将file作为wc命令的输入

>>3.自己实现输入重定向


运行结果:


                            3.简易的myshell实现输入/输出/追加重定向
def.h
#ifndef __DEF_H__
#define __DEF_H__

#define MAXLINE 1024   // 一行的最大值
#define ARGS    8      // 命令行参数个数
#define MAXPIPE 8      // 系统最多能够解析8个管道

typedef struct command_ {
	char *args[ARGS];
	int infd;
	int outfd;
}command_t;


#endif //__DEF_H__

extern.h

#ifndef __EXTERN_H__
#define __EXTERN_H__

#include "def.h"

extern char cmdline[MAXLINE+1];
extern char avline[MAXLINE+1];
extern command_t cmd[MAXPIPE];
extern int pipenum;
extern int lastpid;

#endif //__EXTERN_H__

inti.h

#ifndef __INIT_H__
#define __INIT_H__

void sig_init();
void init();

#endif // __INIT_H__

parse.h

#ifndef __PARSE_H__
#define __PARSE_H__

void shell_loop();
int cmd_read();
int cmd_parse();
int cmd_execute();

#endif // __PARSE_H__

init.c

#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include "init.h"
#include "extern.h"

void handler(int s)
{
	printf("\n[sxshell]: ");
	fflush(stdout);
}

void sig_init()
{
	signal(SIGINT, handler);
	signal(SIGQUIT, SIG_IGN);
}

// 初始化全局变量
void init()
{
	memset(cmdline, 0x00, sizeof(cmdline));
	memset(avline, 0x00, sizeof(avline));
	for (int k=0; k<MAXPIPE; k++) {
		for (int i=0; i<ARGS; i++)
                      cmd[k].args[i] = NULL;
		cmd[k].infd = 0;
		cmd[k].outfd = 1;
	}
	pipenum = 0;
}

parse.c

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>

#include "parse.h"
#include "extern.h"
#include "init.h"

static void cmd_print()
{
	for (int i=0; i<=pipenum; i++) {
		printf("i=%d\n", i);
		for (int j=0; cmd[i].args[j]!=NULL; j++) {
			printf("\t[%s]\n", cmd[i].args[j]);
		}
	}
}

void shell_loop()
{
	while ( 1 ) {
		printf("[sxshell]: ");
		init();
		if ( cmd_read() == 0 )
			break;
		cmd_print();
		cmd_parse();
		cmd_execute();
	}
	printf("\n");
}

/* 读取命令行参数 */
/* 返回值: 成功, 1;失败,0 */
int cmd_read()
{
	return (fgets(cmdline, MAXLINE, stdin)==NULL) ? 0 : 1;
}


// 解析命令行参数
int cmd_parse()
{
	char *p = cmdline;
	char *q = avline;

	for (int i=0; i<MAXPIPE && *p!='\0'; ++i) {
		for (int j=0; j<ARGS && *p!='\0'; ++j) {
			while ( *p!='\0' && (*p==' ' || *p=='\t' || *p=='\n') )
				p++;
			cmd[i].args[j] = q;
			while ( *p!='\0' && *p!=' ' && 
					*p!='\t' && *p!='\n' && *p!='|' ) {
				*q++ = *p++;
			}
			*q++ = '\0';
			
			if ( *p == '|' ) {
				pipenum++;
				p++;
				cmd[i].args[j] = NULL;
				break;
			}
			if ( *p=='\n' ) {
				cmd[i].args[j+1] = NULL;
				break;
			}
		}
	}

	return 0;
}

// 执行指令
int cmd_execute()
{
	int fds[2];

	for (int i=0; i<=pipenum; i++){
		if ( i< pipenum ) {
			pipe(fds);
			cmd[i].outfd = fds[1];
			cmd[i+1].infd = fds[0];
		}
		pid_t pid = fork();
		if ( pid == 0 ) {
			if ( cmd[i].infd != 0 ) {
				close(0);
				dup(cmd[i].infd);
			}
			if ( cmd[i].outfd != 1 ) {
				close(1);
				dup(cmd[i].outfd);
			}
			execvp(cmd[i].args[0], cmd[i].args);
			exit(1);
		}else {
			if ( cmd[i].infd != 0 )
				close(cmd[i].infd);
			if ( cmd[i].outfd != 1 )
				close(cmd[i].outfd);
			lastpid = pid;
		}
                while ( wait(NULL) != lastpid)
		;

	       return 0;
}

main.c

#include "parse.h"
#include "def.h"
#include "init.h"

command_t cmd[MAXPIPE];  // 命令行参数

char cmdline[MAXLINE+1]; // 读取命令行数据
char avline[MAXLINE+1];  // 处理后的数据
int pipenum;             // 当前用了几个管道符
int lastpid;

int main( void )
{
	sig_init();
	shell_loop();
	return 0;
}

Makefile

.PHONY : clean sxshell

OBJS = main.o\
		parse.o\
		init.o
CC=cc
CFLAGS=-Wall -g 

sxshell : $(OBJS)
	$(CC)  $(CFLAGS) -o $@ $(OBJS) -std=gnu99

%.o : %.c
	$(CC) -c $< -o $@ -std=gnu99

clean:
	rm -rf $(OBJS)

运行结果:



Logo

更多推荐