0
点赞
收藏
分享

微信扫一扫

Linux(基础IO详解)

兵部尚输 2023-05-29 阅读 112

目录

关于文件操作的基础知识

操作系统内的文件结构 

文件描述符fd

什么是文件描述符fd

文件描述符fd的分配规则

重定向

dup2函数

将简易shell加上重定向的功能 

对于Linux上一切皆文件的理解

缓冲区

缓冲区的刷新规则 

缓冲区的创建

缓冲区在哪创建的? 

磁盘文件系统

磁盘的物理结构

盘面的存储结构

LBA地址

磁盘的分区和分组

软硬链接 

动静态库 

静态库的实现

动态库的实现 

理解动静态库加载的过程


关于文件操作的基础知识

39dab4e0bfe24544bf2ea8265025415a.png

 

操作系统内的文件结构 

文件描述符fd

什么是文件描述符fd

文件描述符fd的分配规则

重定向

dup2函数

#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>

int main()
{
        char arr[30] = "this is a test";

        int fd = open("test.txt", O_WRONLY | O_CREAT,  S_IRUSR | S_IWUSR | S_IRGRP);
        //此时fd的值因该是3,因为前三个是留给标准输入,输出,错误的

        dup2(fd, 1); //这里利用dup2是fd中文件覆盖标准输出

        printf("%s",arr);//往标准输出中打印字符串
        write(fd, arr, sizeof(arr));//往fd中输出字符串

        //我们能在test.txt中看到arr打印两次
        fflush(stdout);
        return 0;
}

 

将简易shell加上重定向的功能 

//line是命令行字符串,也就是我们用户输入的命令
#define NONE_REDIR 0      //不进行重定向
#define INPUT_REDIR 1     //输入重定向
#define OUTPUT_REDIR 2    //输出重定向
#define APPEND_REDIR 3    //追加输出重定向

//该宏函数用来跳过命令行中的空格
#define trim_space(start) while(isspace(*start)) start++

char line[MAXSIZE];
char* args[100] = {NULL};

int lastcode = 0;
int lastsig = 0;
int redir_type = NONE_REDIR; //重定向标志
char *redir_file = NULL;     //指向被重定向的对象



void commend_check(char *line){
     char* start = line;
     char* end = line + strlen(line);

     while(start < end){
       
      //在这里判断是否出现重定向标识符   
	  if (*start == '>'){    
	     
         //这里把'>'设为'\0'的目的是将前面的命令和后面的重定向对象分割开
         //例如:ls > test.txt,把 > 设为'\0'可以将该字符串分成两部分
         *start = '\0';   
	     start++;
          
         //如果出行两个>>则说明是追加重定向   
	     if (*start == '>'){
	     
         //	*start = '\0'; 这里不用加,一个'\0'就能隔绝了
		    start++;
		    redir_type = APPEND_REDIR;
	     } 
         else{
                redir_type = OUTPUT_REDIR;
	     } 
             
	     trim_space(start);
         redir_file = start;
	     break;
     }
	 else if (*start == '<'){
	        *start = '\0';
		    redir_type = INPUT_REDIR;

	        start++;
	        trim_space(start);
            redir_file = start;
		    break;
	 }
	 else start++;
   }
}

int main(){

  while (1){  
  printf("\n[myshell@vm-centos]$ ");
  fflush(stdout);
  
  //这里的初始化是一定要有的,否则会导致一直进行重定向操作
  redir_type = NONE_REDIR;

  char* s = fgets(line, sizeof(line)-1, stdin);
  assert(s != NULL);
  
  line[strlen(line)-1] = 0;
  
  //命令行的判断一定要在分割字符串之前,否则判断的字符串不完整
  commend_check(line); 
  args[0] = strtok(line," ");
  

  int i = 1;
  
  if(args[0] != NULL && strcmp(args[0], "ls") == 0)
    args[i++] = (char*)"--color=auto";


  while(args[i++] = strtok(NULL," "))
         ; 
  
  if (args[0] != NULL && strcmp(args[0], "cd") == 0){
     if(args[1] != NULL) chdir(args[1]);
     else chdir(getenv("HOME"));
     continue;
  }

  if (args[0] != NULL && strcmp(args[0], "echo") == 0){
     if (args[1] != NULL && strcmp(args[1],"$?") == 0) 
	     printf("%d %d\n", lastcode, lastsig);
     else    printf("%s\n",args[1]);
     continue;
  }


  pid_t id = fork();
  if (id == 0){

    switch(redir_type){
	case NONE_REDIR: break;
        case INPUT_REDIR: {
	    int fd = open(redir_file, O_RDONLY);
	    if (fd < 0) {perror("open"); exit(errno);}
            dup2(fd,0);
        } break;

	case OUTPUT_REDIR:
	case APPEND_REDIR: {
	    umask(0);
	    int file_status = O_WRONLY | O_CREAT;
	    if (redir_type == APPEND_REDIR) file_status |= O_APPEND;
	    else file_status |= O_TRUNC;
	    int fd = open(redir_file, file_status, 0666);
	    if (fd < 0) {perror("open"); exit(errno);}
	    dup2(fd, 1);
	} break;
        
        default: printf("error\n"); break;			   
    }

    execvp(args[0], args);
    exit(0);
  }
      int status;
      pid_t tmp = waitpid(-1, &status, 0); 

      lastcode = ((status>>8) & 0xFF);
      lastsig = (status & 0x7F);

  }
}

对于Linux上一切皆文件的理解

 

 

缓冲区

 

缓冲区的刷新规则 

缓冲区的创建

 

缓冲区在哪创建的? 

  

磁盘文件系统

 磁盘的物理结构

 盘面的存储结构

 

 

 

LBA地址

 

 

磁盘的分区和分组

 

 

软硬链接 

 

动静态库 

静态库的实现

动态库的实现 

理解动静态库加载的过程

 ​​​​​​​​​​

举报

相关推荐

0 条评论