面向过程
*把问题分解为一系列的步骤
*在函数里面一步一步实现这些步骤
*根据实际 需求调用函数
面向对象
*把构成问题的事物分解成一个一个的对象
*调用对象里面的方法属性解决问题
*面向对象有助于维护和扩展代码
面向对象三大特性
*封装性:隐藏封装内部的一些细节
*继承:复用现有的代码
*
一切皆文件
Linux内核
屏蔽硬件区别,把所有的硬件设备抽象成文件,提供统一的接口给用户使用
虚拟文件系统:
抽象层、对文件的访问实际上是对抽象层的访问。
抽象对象:封装了底层读写细节,使用C语言的多态来实现具体文件系统的接口
普通文件系统:
-ext4
-fat32
-ubifs
特殊文件系统:
-进程文件系统:procfs,挂载在/proc,存放进程相关信息,任务管理器。
-设备文件系统:devfs,挂载在/dev。存放硬件操作相关的接口。
文件描述符和打开模式
系统IO编程
*open
*write
*read
*iseek
*close
伪代码:
int fd;
fd=open(filename,flags,mode);
iseek(fd,offset,whence);
write(fd,buf,write_len);
read(fd,buf,read_len);
close(fd);
文件描述符
特殊的索引
实际上就是进程中file_struct结构体成员fd_array的数组下标
文件的打开模式
主模式:
*O_RDONLY:只读模式
*O_WRONLY:只写模式
*O_RDWR:读写模式
副模式:
O_CREATE:当文件不存在,需要去创建文件
O_APPEND:追加模式(把这个文件的读写位置设置到文件的尾巴)
O_DIRECT:直接IO模式(write函数和read函数里面读取的数据不需要通过页缓存区)
O_SYNC:同步模式(所有数据都会从页缓存区写到磁盘里面去)
O_NOBLOCK:非阻塞模式()
进程
每个程序本质上就是一个进程
标准IO编程
open_close函数
OPEN函数
头文件:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
函数原型:
- 当文件存在时:
int open(const char* pathname,int flags)
-----这两个函数的主要区别就是第三个参数
例子:
当文件不存在时:
int open (const char* pathname,int flags,int perms)
①pathname
②flags:文件的打开模式
主模式:1.O_RDONLY:只读模式 2 .O_WRONLY:只写模式 3.O_RDWR:读写模式
副模式:1.O_CREATE:当文件不存在,需要去创建文件(剩下的用到再说吧)
O_APPEND:追加模式
O_DIRECT:直接IO模式
O_SYNC:同步模式
O_NOBLOCK:非阻塞模式
③perms:指定文件权限如0777,0666.
int fd = open("file",O_RDWR|O_CREAT,0666);
返回值
成功:文件描述符
失败:-1
CLOSE函数
头文件:
#include <unistd.h>
函数原型:
int close(int fd)
返回值:
成功:0
失败:-1
lseek函数
使用lseek函数之前先要包含头文件#include <unistd.h>
函数原型
ssize_t read(int fd,void *buff,size_t count)
需要三个参数
{
1.int fd:用open文件返回来的文件描述符
2.void *buff:读取文件后所需要填充到的buff地址
3.size_t count:返回值
成功:
①返回值为count:成功读取全部字节
②0~count:
剩余文件长度小于count
读取期间被异步信号打断
③失败:
-1,读取错误
}
write函数
使用write函数之前需要包含头文件同read函数的头文件一样#include <unistd.h>
函数原型(跟read函数很像)
ssize_t write(int fd,void *buff,size_t count)
{
①int fd:用open文件返回来的函数描述符
②void *buff:写入内容的buff地址,例如(“123”)
③size_t count:返回值 (字节数)
如果成功:①count:成功写入全部字节
② 0~count(大于0小于count): 写入期间被异步信号打断
如果失败: -1,读取错误
}
实现复制普通文件功能的小实验
#include <unistd.h> //使用到read、write函数把头文件包含进来
#include <sys/types.h> //用到open函数把头文件包含进来
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h> //因为后续会用到printf函数打印
int main(int argc,char** argv) //main函数需要接收从控制台传来的参数
{
int fd1,fd2; //定义两个open文件描述符
char buf[512]; //定义一个512字节的缓冲区
int read_size; //read_size用来表示读取的字节数量
if(agrc != 3) //判断如果main函数接收到的参数数量不等于3的话,让它报错
{
printf("param error!\r\n");
return -1;
}
fd1 = open(argv[1],O_RDONLY);//打开要复制的文件,参数名保存在main函数的第一个参数里,打开模式为只读模式,把返回的文件描述符赋值给fd1的变量
fd2 = open(agrv[2],O_WRONLY|O_CREAT,0666); //用open函数去创建一个新的文件且模式为只写模式,O_CREAT的副模式,也就是说当我们这个文件不存在的时候,创建一个新文件,最后指定文件权限
if(fd1 < 0 || fd2 < 0) //只要有1个函数返回值小于0,说明打印错误
{
printf("open error!!\r\n"); //
return -1;
}
while(1)
{
read_size = read(fd1,buf,512); //读取要复制的文件,缓冲区buf地址,读取文件内容的字节大小512
if(read_size == 0) //如果读取到字节数量等于0,退出循环
break;
write(fd2,buf,read_size); //
}
//用close函数关闭我们打开的文件描述符
close(fd1);
close(fd2);
return 0;
}
1、打开要复制的文件
2、创建新的文件
3、把源文件内容读到缓冲区,把缓冲区内容写入新文件
4、循坏执行第三步,直到读取的字节数量为0,退出循坏。
5、关闭打开的文件
#定义变量
#ARCH默认使用
ARCH ?= X86
ifeq ($(ARCH),X86)
CC=gcc
else
CC=arm-linux-gnueabihf-gcc
endif
TARGET=copy
#OBJS=main.o mp3.o
BUILD_DIR=build
SRC_DIR=.
INC_DIR=.
CFLAG=$(patsubst %,-I%,$(INC_DIR))
INCLUDES=$(foreach dir,$(INC_DIR),$(wildcard $(dir)/*.h))
SOURCES=$(foreach dir,$(SRC_DIR),$(wildcard $(dir)/*.c))
OBJS=$(patsubst %.c,$(BUILD_DIR)/%.o,$(notdir $(SOURCES)))
VPATH=$(SRC_DIR)
$(BUILD_DIR)/$(TARGET):$(OBJS)
$(CC) $^ -o $@
$(BUILD_DIR)/%.o:%.c $(INCLUDES) | create_build
$(CC) -c $< -o $@ $(CFLAG)
.PHONY:clean create_build
clean:
rm -r $(BUILD_DIR)
create_build:
mkdir -p $(BUILD_DIR)
~
sudo mv 1.tst 1.txt // 如果名字写错了,可以这样把它改过来哦
这样就可以把1.txt的内容复制到2.txt里面
lseek函数
lseek函数的功能主要是设置文件读写位置
使用lseek函数之前需要包含头文件#include <unistd.h>
函数原型
off_t lseek(int fd,off_t offset,int whence)
lseek函数有三个参数
{
1.(int fd)调用open函数返回的文件描述符
2.(off_t offset):设计一个偏移量
3.(int whence):相对的基准点
若whence为SEEK_SET,基准点为文件开头
若whence为SEEK_CUR,基准点为当前位置
若whence为SEEK_END,基准点为文件末尾
返回值
如果成功:返回值等于文件偏移位置值
如果失败:返回值等于-1
}
例如:
lseek(fd,100,SEEK_CUR); //偏移量的位置为100个字节 基准点为当前位置
ARCH ?= X86
TARGET=test_lseek
BUILD_DIR=build
SRC_DIR=.
INC_DIR=.
CFLAG=$(patsubst %,-I%,$(INC_DIR))
INCLUDES=$(foreach dir,$(INC_DIR),$(wildcard $(dir)/*.h))
SOURCES=$(foreach dir,$(SRC_DIR),$(wildcard $(dir)/*.c))
OBJS=$(patsubst %.c,$(BUILD_DIR)/%.o,$(notdir $(SOURCES)))
VPATH=$(SRC_DIR)
$(BUILD_DIR)/$(TARGET):$(OBJS)
$(CC) $^ -o $@
$(BUILD_DIR)/%.o:%.c $(INCLUDES) | create_build
$(CC) -c $< -o $@ $(CFLAG)
.PHONY:clean create_build
clean:
rm -r $(BUILD_DIR)
create_build:
mkdir -p $(BUILD_DIR)
sudo vi file //123偏移100个字节abc
sync函数
页缓存和回写功能:强制把修改过的页缓存区数据写入磁盘
使用sync函数时需要包含头文件#include <unistd.h>
函数原型:void sync(void);
返回值
无
这个sync实验结果不明显,以后碰到再写过!
使用sync()函数就能保证write里面的数据能够及时写入磁盘里面去
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
int main()
{
int fd = open("file",O_RDWR|O_CREAT,0666);
write(fd,"123",3);
lseek(fd,100,SEEK_CUR);
write(fd,"abc",3);
sync();
close(fd);
return 0;
}
标准IO函数
C标准库实现了一个IO缓存区
常见标准IO函数
①fopen
打开一个文件
②fclose
关闭一个文件
③fread
读取文件内容
④fwrite
把内容写到文件里面去
⑤fseek
设置文件的读写位置
⑥fflush
强制把IO缓存区的数据写入到页缓存区
文件IO五大模式
①阻塞模式
②非阻塞模式
③IO多路复用
④异步IO
⑤信号驱动IO
好了睡觉。。。