1.开发分类
1.1 “裸奔”
APP
————————————————
hardware(硬盘)
好处
简单 可以直接操作硬件
坏处
必须要懂硬件 同时还要会写程序
没有并发 不能同时运行多个任务 SuperLoop
1.2 OS Operation system
APP
——————————————————
OS(操作系统)
——————————————————
hardware(硬盘)
特点
可以把精力放在业务逻辑 而不需要操行硬件的问题
并发
OS?
软件
操作系统是管理和分配硬件资源的系统软件
linux操作系统下进行硬件开发,就是调用系统的API函数
去操作硬件,或者是去使用linux提供的服务
open
close
read
write
.....
2.linux是一个什么东西?
linux是一个开源的操作系统
设计哲学
everything is file in linux
在Linux下一切皆文件
在linux下 无论要操作什么其实都是操作文件
或者说 在linux下面 操作任何东西 都是通过文件的接口去实现
文件系统 用来存储 管理 组织文件的一套方式 方法 协议及其软件的实现
文件:
文件属性 i-node 它是唯一标识文件存在与否的东西
文件内容
文件操作过程
linux内核中的两个东西
struct inode{} 用来描述文件的物理inode信息的
系统识别到一个文件存在,就会为它创建一个Inode的节点
一个inode节点只会对应一个文件
struct file{} 用来描述一个已经打开的文件
文件的状态的标记 O_RDONLY O_WRONLY O_RDWR....
文件偏移量/offset 类似光标
struct inode*
每一个打开的文件都会对应一个struct file
一个文件可以被不同的进程打开
操作的流程
进程文件表项 找到对应的struct file-》struct Inode -》硬件上Inode的节点-》文件内容
高内聚 低耦合
linux为了屏蔽文件操作的具体细节 为每一个进程创建一个
进程文件表项的东西 保存了每个进程打开文件的指针
进程文件表项是一个数组
struct flie *fds[]
0 struct file* ->struct file
1 ....
2 .....
linux 提供了操作文件的函数接口
open 打开一个文件 返回值就是进程文件表项的下标 int
“文件描述符” fd 在linux应用用来描述一个打开的文件
是这个打开文件的唯一ID 后续操作文件都是通过这个ID
read
write
....
---------------------------
linux系统提供的操作文件的函数 统称为系统IO
3.linux系统IO的使用
1.打开文件open
man -f open 确定要open的那个章节
man 2 open
NAME
open, openat, creat - open and possibly create a fileSYNOPSIS
//头文件 使用这些函数 需要包含那些头文件
#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, mode_t mode);
const char *pathname:要打开的文件名 指的是文件绝对/相对路径 相对目前程序运行的路径
int flags: 打开文件,什么方式打开
O_RDONLY 只读打开 read only
O_WRONLY 只写打开 write only
O_RDWR 读写打开 read write
上面三个文件标记 三选一
note: O_RDWR 不等于 O_RDONLY | O_WRONLY!!!!
O_APPEND 追加打开 文件偏移量在文件的末尾
O_CREAT 创建标记 如果文件不存在 则创建文件
O_EXCL 该标记一般和O_CREAT配合使用,用来测试文件是否存在
note:如果指定 O_EXCL|O_CREAT 如果文件存在 则open失败
errno == EEXIST
O_TRUNC 截短的标志 把文件所有的内容清空
O_NONBLOCK 非阻塞方式打开文件
非阻塞 是不等待的意思
如果文件没有内容 read不阻塞 直接返回错误
如果硬盘没有空间 write不阻塞 直接放回错误
阻塞 要等
如果文件没有内容 read阻塞 直到有数据或出错
如果硬盘没有空间 write阻塞 直到可写或出错
...
多个标记用‘|’链接
O_RDWR | O_TRUNC | O_NONBLOCK
mode_t mode :指定创建文件时的权限,当第二个参数带有O_CREAT"
需要指定创建的文件权限是什么
有两种方式去指定
rwx rwx rwx
第一组rwx这个文件所有者的权限 USER
第二组rwx这个文件所有者同组人权限 Group
第三者rwx其他人的权限 Other
(1)所有可能权限
读写执行 | 读 | 写 | 执行 |
S_IRWXU | S_IRUSR | S_IWUSR | S_IXUSR |
S_IRWXG | S_IRGRP | S_IWGRP | S_IXGRP |
S_IRWXO | S_IROTH | S_IWOTH | S_IXOTH |
例子:
S_IRWXU|S_IRGRP|S_IROTH
rwxr--r--
(2)0744 <==> rwxr--r--
r 4 w 2 x 1
返回值
成功返回一个打开的文件描述符(>2)
文件描述符>2是系统为每个进程打开了三个文件
标准输入文件 文件描述符 STDIN_FILENO(0)
标准输出文件 文件描述符 STDOUT_FILENO(1)
标准出错文件 文件描述符 STDERR_FILENO(2)
失败返回-1 同时errno被设置
errno是一个全局变量 是用来保存最后出错的错误码
perror 把错误码的提示答应出来
perror("你的提示")
你的提示:错误码的提示
创建一个文件 名为1.txt 如果文件存在则创建失败 如果文件不存在则创建
权限为 rwx r-- r--
2.操作文件
read
read - read from a file descriptor
SYNOPSIS
#include <unistd.h>ssize_t read(int fd, void *buf, size_t count);
int fd:要读那个文件
void buf: 读到的数据存到buf里面
size_t count; 要读多少个字节
返回值 成功 返回实际读取的字节数
>0 (可能小于)实际读取的字节数
=0 读到文件末尾
失败 返回-1 同时errno被设置
write
NAME write - write to a file descriptor
SYNOPSIS
#include <unistd.h>ssize_t write(int fd, const void *buf, size_t count);
int fd:要写那个文件
const void * buf: 要写入文件的数据存放在哪里?
size_t count: 要写多少个字节
返回值 成功 返回实际写入的字节数
>0 (可能小于)实际写入的字节数
=0 磁盘空间已满 写不进去了 什么都没有写进去
失败 返回-1 同时errno被设置
练习 从一个文件读取n个字节 并打印出来
将一串字符串写入到文件中
lseek
NAME
lseek - reposition read/write file offsetSYNOPSIS
#include <sys/types.h>
#include <unistd.h>off_t lseek(int fd, off_t offset, int whence);
将光标移动到指定的位置
int fd : 要操作文件的文件描述符
off_t offset: 偏移量 相对whence的距离 可以正 可以是负的
int whence: 定位方式 offset是基于什么偏移
SEEK_SET 基于文件开头
SEEK_CUR 基于文件当前位置
SEEK_END 基于文件末尾
返回值
成功返回 新光标距离文件开头的位置
失败返回 -1 同时errno被设置
怎么获取文件大小? lseek(fd,0,SEEK_END); 返回值就是文件的大小
关闭文件
#include <unistd.h>
int close(int fd);
int fd : 要关闭文件的文件描述符
返回值
成功返回0
失败返回-1 同时errno被设置
总结:
1.理解裸奔开发与OS开发的区别
计算机科学中的任何问题,都可以通过加上一层逻辑层解决
任何问题都可以通过细分去解决
2.linux文件操作流程
struct inode
struct file
文件描述符 是struct file 在进程文件表项中下标 > 0
系统IO linux系统提供一套用于文件操作的API函数接口
打开文件 -》操作文件-》关闭文件
3.系统IO 不需要记具体用法 参数
记住名字就可以 因为有man