目录
关于文件操作的基础知识
操作系统内的文件结构
文件描述符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地址
磁盘的分区和分组
软硬链接
动静态库
静态库的实现
动态库的实现
理解动静态库加载的过程