笔记整理—内核!启动!—linux应用编程、网络编程部分(1)API概述与文件I/O
文件I/O即为文件的input和output的功能。
操作系统的API:
学习操作系统的本质就是学习一个操作系统提供的API。
常用的IO:open、close、write、read、lseek。 打开一个文件(open)得到一个文件描述符,读写文件使用(read、write、lseek),关闭文件使用(close)。
对于linux而言,打不开文件就干不了活,使用完毕文件不进行关闭容易造成文件损坏。
文件平日存在块设备里,通过文件系统进行管理,最底层表现为扇区。存在块设备中的未打开文件是静态文件。
内核中在进程建立一个打开的文件数据结构,记录下整个文件。开辟申请一段内存,将静态文件读取到内存中得到一个动态文件。打开后的操作是针对内存中复制的这个文件,而不是块中的文件。close整个文件后将内存中的动态文件更新到块设备,更新静态文件。
块设备只能按照扇区操作。不支持随机访问,要改就是改一块,内存支持随机访问,读取、更改,说是那就是那,这就是随机访问(RAM-random)。
文件描述符的实质就是一个数字,用于区分不同的动态文件,一个程序打开,就会创建一个文件描述符,多个文件,就可以用文件描述符进行区分。
int fd=-1;
fd=open("a.txt",O_RDWR);
if(-1==fd)
{
printf("err\n");
}
printf("fd=%d",fd);
close(fd);
open的文件描述符一定要保存好。
ssize_t read (int fd, void *buf, size_t count);
fd是文件描述符,代表了是那个文件;*buf提供了一个内存的缓冲区,用于存储读取的内容;count为读取多少字节的数据。
ssize_t是使用typedef重新定义的int类型数据,返回数据则为成功读取到的字节数。
char buf[100]={0};
int ret=-1;
ret=read(fd,buf,20);
if(-1==ret)
{
printf("err\n");
}
else
{
printf("ret=%d,buf=%s",ret,buf);
}
close(fd);
ssize_t write (int fd, const void * buf, size_t count);
在fd指向的文件写入count个buf中的字节数。
char writebuf[20]=“xxxx”;
int ret=-1;
ret=write(fd,writebuf,strlen(writebuf));
if(ret<0)
{
printf("err\n");
}
else
{
printf("ret=%d,writebuf=%s",ret,writebuf);
}
close(fd);
open()函数的flag:与读写权限相关,O_RDONLY只读、O_WRONLY只写、O_RDWR可读可写。打开一个有内容的文件一般会进行三种写的操作①新内容覆盖旧内容。②接续写。③写在头部。
O_TRUNC:会使打开的文件的内容清除。
O_APPEND接续内容。
O_TRUNC会顶掉O_APPEND操作。
打开文件错误时退出进程: return -1;return只能在mian中使用,所以一般使用exit\_exit\_Exit终止进程,如_exit(-1);
打开的文件不存在:O_CREAT表示已知所打开的文件不存在,需要进行创建,创建后再打开。open("a.txt",O_RDWR|O_CREAT)。如果文件存在,则会将文件重新创建。
使用O_EXCL和O_CREAT结合,文件存在则会报err,文件不存在则会被创建。同时使用O_CREAT创建文件时可赋予文件权值。open("a.txt",O_RDWR|O_CREAT,0666);
O_NONBLOCK只用于设备文件,不会用于普通文件,非阻塞式,要么操作成功,要么报err,不排队不等待,保障了时间,但不保障结果,多用于dcntl函数,打开设备文件。一般情况下打开一个文件是默认为阻塞的。
O_SYNC非阻塞式,正常没有O_SYNC的情况下,缓冲区接受完成buf会一次性写入块设备,若O_SYNC则缓冲区有一个内容就会立刻对内容进行处理,不等待buf全部进入缓冲区。正常情况下,buf会先写入缓冲区,再一次性写入设备,这对设备的寿命有利。
error number错误码,常见的错误都有对应的错误码,当函数执行错误时,会返回一个number。errno由操作系统进行维护,os内部函数都可进行设置errno去报告对应的errno。linux提供一个函数perror去对接errno,不用传参,通过数字传递相关信息。void perror(count char *s)->perror(“文件打开错误”),打印相关错误信息的时候,会附加上错误原因的,由errno的接口才能使用perror。
值得一提的是,如果读串口使用阻塞模式读30个字节,但只读了20个字节时,就会等待余下的10个字节,有时候传输的数据很大时,应会多次读取进行传输。
文件的I/O指定是open、close、write等API,能干活但是效率不新,本质上系统层与应用层之间是存在差异的如count的大小。
C库函数提供了标准I/O,fopen、fwrite等库函数,这些IO函数,是通过系统的文件IO库二次封装而来的,主要是再应用层提供了缓冲机制,fwrite的内容先进应用层buf,再根据最佳选择运输到内核buf,内核再根据最佳选择写入块设备。
本质上就是为了提高传输的效率。