【操作系统---11】基础IO和minishell增加重定向功能

标准库IO接口:


fread接口:

			size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);

参数解释:

			ptr:用于接收数据的缓冲区
	
			size:要读取的块大小

			nmemb:被读取的块大小

			stream:文件流指针

fseek接口:

			int fseek(FILE *stream, long offset, int whence);
	
			功能:对stream文件的读写位置跳转到从whence位置偏移offset个字节处	

参数解释:

			SEEk_SET	文件的起始位置

			SEEK_CUR	当前读写位置

			SEEK_END	文件末尾位置
			
			offset偏移量

			fseek(fp,0,SEEK_SET)	最后一定要记得fclose();

系统调用IO接口:

常用的接口:open write read lseek close

包含的头文件#include <fcntl.h>


open接口:

			int open(const char *pathname, int flags, mode_t mode);

			功能:打开文件

			pathname:指定要打开的文件名称

flags:选项参数

			必选参数:O_RDONLY, O_WRONLY, or O_RDWR	三个只能选择一个

			可选参数:O_CREAT		若文件存在则打开,不存在就创建新文件

					O_EXCL		与O_CREAT同时使用,若文件存在则报错,不存在则创建

					O_TRUNC		打开文件同时截断文件为0长度

					O_APPEND	写入数据总是写入末尾

返回值:文件描述符(正整数) 失败:-1

必须参数选择一个可以或上可选参数多个,满足多种需求


write接口:

			ssize_t write(int fd, const void *buf, size_t count);

			功能:写入数据

参数解释:

			fd:open打开文件返回的文件描述符

			buf:要写入的数据

			count:要写入的字节数

返回值:实际写入的字节数 失败:-1


lseek接口:

			off_t lseek(int fd, off_t offset, int whence);

			功能:跳转fd的读写位置到指定位置

read接口:

			ssize_t read(int fd, void *buf, size_t count);

			返回值:返回实际读取到的字节数,失败返回-1	

close接口:

			int close(int fd);

			功能:关闭文件

文件描述符:

正整数 sda:表示SATA的接口的第一块硬盘,第27块表示为sdaa

struct file是用数组来组织的 结构体指针数组

内核中文件描述信息结构体数组的下标

分配规则:	最小未使用	一个进程运行起来默认先打开三个文件	
			
						标准输入,标准输出,标准错误文件

						 0	       1		2	     int文件描述符

					    stdin   stdout    stdeeor	 File*文件流指针




Q:文件描述符和文件流指针的关系?

A:printf	向标准输出文件写入数据	FILE*fp-->_fileno	通过这个fileno找到文件描述符

重定向:

指的是文件描述符的重定向,文件描述符这个下标中的文件描述信息,从一个文件变成了另一个文件

这个时候用户通过文件流指针向文件写入数据的时候,文件描述符没变,但是描述符下标的文件描述信息已经改变

	>>追加重定向	O_APPEND

	> 清空重定向	O_TRUNC

int dup2(int oldfd, int newfd);

将oldfd描述符对应的描述信息,向newfd中拷贝一份,让newfd也指向oldfd所指向的文件,若newfd本身已经有打开文件,会先关闭这个文件,让newfd重定向到oldfd

minishell增加重定向功能:

思路分析:

<1>对输入的字符串进行检测,遇到>符号之前的,作为命令以及参数解析
<2>遇到>之后紧跟>即为追加重定向,只有一个>为清空重定向
<3>符号>之后的字符串是文件名称
<4>按照重定向的方式打开文件,然后使用dup2进行重定向

代码实现:

检测操作:

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

int main()
{
		while (1)
		{
			printf("[luzihan@TecentCloud]$");
			fflush(stdout);
			
			char tmp[1024] = { 0 };
			scanf("%[^\n]%*c",tmp);
			printf("%s\n", tmp);
			
		    char* ptr=tmp;

			//用来判断是追加重定向还是清空重定向的标记
		    int _flag=0;
		    char* _file=NULL;
		    while(*ptr!='\0')
		    {
		    	//遇到第一个>,说明前面的字符串是命令以及参数
		    	//如果只有一个>,说明是清空重定向,更改标记为1
		    	//加上\0使前面的字符串完整,可以解析
		        if(*ptr=='>')
		        {
				    *ptr='\0';
				    ptr++;
				    _flag=1;
	       
	       		   //如果遇到第二个>,说明是追加重定向,更改标记
	       		   //同理,加上\0,使字符串完整可以获得解析
				   if(*ptr=='>')
				   {
				      *ptr='\0';
					  ptr++;
				      _flag=2;
				   }
				   
				   //如果这时ptr是空字符,说明还没到文件名称,ptr继续往后走
				   while(isspace(*ptr)&&*ptr!='\0')
				   {
				      ptr++;
				   }
				   
				   //ptr这时不为空字符且不为\0,开始读取文件名称
				   _file=ptr;
				 
				   //ptr不是空字符继续往后读取,直到遇到空字符,读取完毕,手动添加\0
				   while(!isspace(*ptr)&&*ptr!='\0')
				   { 
				       ptr++;
				   }
				   *ptr='\0';
				 }
				 
				 //如果没有遇到>,就往后走,解析字符串
	    	     ptr++;
	 	     }

IO操作:

		//创建子进程,进行程序替换
		int pid = fork();
		if (pid == 0)
		{	      
			int fd=1;
	        if(_flag==1)
	        {
		 		 fd=open(_file,O_CREAT|O_WRONLY|O_TRUNC,0664);
	        }
	        else if(_flag==2)
	        {
	          	 fd=open(_file,O_CREAT|O_WRONLY|O_APPEND,0664);
	        }
	        
	        dup2(fd,1);
			execvp(argv[0], argv);
			//进程创建失败直接退出
			exit(0);
		}	

代码运行测试图:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值