今天我来总结一下Linux中的基础I/O的相关知识。
一。open/read/write/close函数。
1.open:int open(const char *path,int flag,mode_t Mode):打开或创建文件。
2.read:ssize_t read(int fd,void *buf,size_t len);从文件中读取数据。返回实际读取的字节数。
3.write:ssize_t write(int fd,const char *buf,size_t len);往文件里写数据。返回实际写出去多少字节。
4.close:关闭文件。int close(int fd);
举例应用:
#include<stdio.h>
2 #include<string.h>
3 #include<unistd.h>
4 #include<stdlib.h>
5 #include<fcntl.h>
6
7 int main(void)
8 {
9 int fd=open("tmp",O_RDWR|O_CREAT,0644);
10 printf("fd=%d\n",fd);
11 close(1);
12 int nfd=dup(fd);
13
14 printf("nfd=%d\n",nfd);
15 write(nfd,"abc",3);
16
17 close(fd);
18 close(nfd);
19 }
~
[ymk@localhost d4]$ cat tmp
nfd=1
abc
二。fd与FILE结构体。
1.fd:文件描述符。一般有stdin: 0 标准输入文件;stdout:1 标准输出文件;stderr:2 标准出错。
2.FILE结构体:
//C语言文件指针域文件描述符之间可以相互转换
int fileno(FILE * stream)
FILE * fdopen(int fd, const char * mode)
struct _iobuf {
char *_ptr; //缓冲区当前指针
int _cnt;
char *_base; //缓冲区基址
int _flag; //文件读写模式
int _file; //文件描述符
int _charbuf; //缓冲区剩余自己个数
int _bufsiz; //缓冲区大小
char *_tmpfname;
};
typedef struct _iobuf FILE;
三动/静态库的应用。
1.静态库:
#include"add.h"
2 int add(int a,int b)
3 {
4 return a+b;
5 }
6 #include"sub.h"
7 int sub(int a,int b)
8 {
9 return a-b;
10 }
11 #include"mul.h"
12 int mul(int a,int b)
13 {
14 return a*b;
15 }
16 #include"div.h"
17 int div(int a,int b)
18 {
19 return a/b;
20 }
首先这是main函数,其它加减乘除的小程序就不展示了。
1 #include<stdio.h>
2 #include"add.h"
3 #include"sub.h"
4 #include"mul.h"
5 #include"div.h"
6
7 int main()
8 {
9 int a=10;
10 int b=5;
11 printf("%d+%d=%d\n",a,b,add(a,b));
12 printf("%d-%d=%d\n",a,b,sub(a,b));
13 printf("%d*%d=%d\n",a,b,mul(a,b));
14 printf("%d/%d=%d\n",a,b,div(a,b));
15 }
这是Makefile文件,将.c变为.o
1 .PHONY : clean
2 main : main.o add.o sub.o mul.o div.o
3 gcc main.o add.o sub.o mul.o div.o -o main
4 main.o : main.c
5 gcc -c main.c -o main.o
6 add.o :add.c
7 gcc -c add.c -o add.o
8 sub.o :sub.c
9 gcc -c sub.c -o sub.o
10 mul.o :mul.c
11 gcc -c mul.c -o mul.o
12 div.o :div.c
13 gcc -c div.c -o div.o
14 clean :
15 rm -rf *.o main
生成静态库:
[ymk@localhost d5]$ make
gcc -c main.c -o main.o
gcc -c add.c -o add.o
gcc -c sub.c -o sub.o
gcc -c mul.c -o mul.o
gcc -c div.c -o div.o
gcc main.o add.o sub.o mul.o div.o -o main
[ymk@localhost d5]$ ar -cr libymk.a add.o sub.o mul.o div.o
[ymk@localhost d5]$ ar -tv libymk.a
rw-rw-r-- 1000/1000 1240 Jul 9 20:38 2018 add.o
rw-rw-r-- 1000/1000 1240 Jul 9 20:38 2018 sub.o
rw-rw-r-- 1000/1000 1240 Jul 9 20:38 2018 mul.o
rw-rw-r-- 1000/1000 1240 Jul 9 20:38 2018 div.o
[ymk@localhost d5]$ gcc main.c -L. -lymk
[ymk@localhost d5]$ ./a.out
10+5=15
10-5=5
10*5=50
10/5=2
2.动态库:
[ymk@localhost d5]$ ls
add.c add.h a.out div.c div.h main.c Makefile mul.c mul.h sub.c sub.h
[ymk@localhost d5]$ gcc -fPIC -shared -o libymk.so add.c sub.c mul.c div.c
[ymk@localhost d5]$ gcc main.c -L. -lymk
[ymk@localhost d5]$ ls
add.c a.out div.h main.c mul.c sub.c
add.h div.c libymk.so Makefile mul.h sub.h
[ymk@localhost d5]$ LD_LIBRARY_PATH=. ./a.out
10+5=15
10-5=5
10*5=50
10/5=2
四。shell。
#include<stdio.h>
#include<string.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
//1.建立一个子进程(fork)
//2.在子进程中获取命令行
//3.在子进程中解析命令行,并判断是那种重定向替换相应的文件描述符
//4.替换子进程(execvp)
//5.父进程等待子进程退出(wait)
void Run(char *buf,char *argv[]){
while(1){
//打印提示符
printf("[MyShell]$");
fflush(stdout);
//创建子进程
pid_t id = fork();
if(id < 0){
perror("fork");
}else if(id == 0){
//子进程
char *str = NULL;
int argc = 0;
//获取命令行
gets(buf);
//判断是那种重定向,并替换相应文件描述符
if(str = strstr(buf,">>")){
//追加重定向
*str = '\0';
str++;
str++;
while(*str == ' '){
str++;
}
//关闭标准输出,并打开追加重定向要追加的文件
close(1);
int fd = open(str,O_WRONLY|O_APPEND);
if(fd != 1){
perror("open");
return;
}
}else if(str = strstr(buf,"<")){
//输入重定向
*str = '\0';
str++;
while(*str == ' '){
str++;
}
//关闭标准输入,并打开输入重定向要输入的文件
close(0);
int fd = open(str,O_RDONLY);
if(fd != 0){
perror("open");
return;
}
//获取文件内容,得到命令
gets(buf);
}else if(str = strstr(buf,">")){
//输出重定向
*str = '\0';
str++;
while(*str == ' '){
str++;
}
//关闭标准输出,并打开输出重定向要输出的文件
close(1);
int fd = open(str,O_WRONLY|O_CREAT,0644);
if(fd != 1){
perror("open");
return;
}
}
//解析命令
argv[argc] = strtok(buf," ");
while(argv[argc]){
argv[++argc] = strtok(NULL," ");
}
//子进程程序替换
execvp(argv[0],argv);
perror("execvp");
}else{
//父进程等待子进程
wait(NULL);
}
}
}
int main(){
char buf[1024] = {0};
char *argv[8] = {NULL};
Run(buf,argv);
return 0;
}