linux文件io(linux嵌入式软件开发)

很多朋友对于linux文件io和linux嵌入式软件开发不太懂,今天就由小编来为大家分享,希望可以帮助到大家,下面一起来看看吧!

Linux异步IO

Linux中最常用的IO模型是同步IO,在这个模型中,当请求发出之后,应用程序就会阻塞,直到请求满足条件为止。这是一种很好的解决方案,调用应用程序在等待IO完成的时候不需要占用CPU,但是在很多场景中,IO请求可能需要和CPU消耗交叠,以充分利用CPU和IO提高吞吐率。

下图描绘了异步IO的时序,应用程序发起IO操作后,直接开始执行,并不等待IO结束,它要么过一段时间来查询之前的IO请求完成情况,要么IO请求完成了会自动被调用与IO完成绑定的回调函数。

Linux的AIO有多种实现,其中一种实现是在用户空间的glibc库中实现的,本质上是借用了多线程模型,用开启的新的线程以同步的方式做IO,新的AIO辅助线程与发起AIO的线程以pthread_cond_signal()的形式进行线程间的同步,glibc的AIO主要包含以下函数:

1、aio_read()

aio_read()函数请求对一个有效的文件描述符进行异步读操作。这个文件描述符可以代表一个文件、套接字,甚至管道,aio_read()函数原型如下:

aio_read()函数在请求进行排队之后就会立即返回(尽管读操作并未完成),如果执行成功就返回0,如果出现错误就返回-1。参数aiocb(AIO I/O Control Block)结构体包含了传输的所有信息,以及为AIO操作准备的用户空间缓冲区。在产生IO完成通知时,aiocb结构就被用来唯一标识所完成的IO操作。

2.aio_write()

aio_write()函数用来请求一个异步写操作。函数原型如下:

aio_write()函数会立即返回,并且它的请求以及被排队(成功时返回值为0,失败时返回值为-1)

3.aio_error()

aio_error()函数被用来确定请求的状态,其原型如下:

该函数的返回:

4.aio_return()

异步IO和同步阻塞IO方式之间有一个区别就是不能立即访问函数的返回状态,因为异步IO没有阻塞在read()调用上。在标准的同步阻塞read()调用中,返回状态是在该函数返回时提供的。

但是在异步IO中,我们要用aio_return()函数,原型如下:

只有在aio_error()调用确定请求已经完成(可能成功、也可能发生了错误)之后,才会调用这个函数,aio_return()的返回值就等价于同步情况中read()或者write系统调用的返回值。

5.aio_suspend()

用户可以用该函数阻塞调用进程,直到异步请求完成为止,调用者提供了一个aiocb引用列表,其中任何一个完成都会导致aio_suspend()返回。函数原型如下:

6.aio_cancel()

该函数允许用户取消对某个文件描述符执行的一个或所以IO请求。

要取消一个请求,用户需要提供文件描述符和aiocb指针,如果这个请求被成功取消了,那么这个函数就会返回AIO_CANCELED。如果请求完成了,就会返回AIO_NOTCANCELED。

7.lio_listio()

lio_listio()函数可用于同时发起多个传输。这个函数非常重要,它使得用户可以在一个系统调用中启动大量的IO操作,原型如下:

mode参数可以是LIO_WAIT或者是LIO_NOWAIT。LIO_WAIT会阻塞这个调用,直到所有的IO都返回为止,若是LIO_NOWAIT模型,在IO操作完成排队之后,该函数就会返回。list是一个aiocb的列表,最大元素的个数是由nent定义的。如果list的元素为null,lio_listio()会将其忽略。

如何提高Linux服务器磁盘io性能

您好,很高兴为您解答。

在现有文件系统下进行优化:

linux内核和各个文件系统采用了几个优化方案来提升磁盘访问速度。但这些优化方案需要在我们的服务器设计中进行配合才能得到充分发挥。

文件系统缓存

linux内核会将大部分空闲内存交给虚拟文件系统,来作为文件缓存,叫做page cache。在内存不足时,这部分内存会采用lru算法进行淘汰。通过free命令查看内存,显示为cached的部分就是文件缓存了。

如何针对性优化:

lru并不是一个优秀淘汰算法,lru最大的优势是普适性好,在各种使用场景下都能起到一定的效果。如果能找到当前使用场景下,文件被访问的统计特征,针对性的写一个淘汰算法,可以大幅提升文件缓存的命中率。对于http正向代理来说,一个好的淘汰算法可以用1GB内存达到lru算法100GB内存的缓存效果。如果不打算写一个新的淘汰算法,一般不需要在应用层再搭一个文件cache程序来做缓存。

最小分配:

当文件扩大,需要分配磁盘空间时,大部分文件系统不会仅仅只分配当前需要的磁盘空间,而是会多分配一些磁盘空间。这样下次文件扩大时就可以使用已经分配好的空间,而不会频繁的去分配新空间。

例如ext3下,每次分配磁盘空间时,最小是分配8KB。

最小分配的副作用是会浪费一些磁盘空间(分配了但是又没有使用)

如何针对性优化:

我们在reiserfs下将最小分配空间从8KB改大到128K后提升了30%的磁盘io性能。如果当前使用场景下小文件很多,把预分配改大就会浪费很多磁盘空间,所以这个数值要根据当前使用场景来设定。似乎要直接改源代码才能生效,不太记得了,09年的时候改的,有兴趣的同学自己google吧。

io访问调度:

在同时有多个io访问时,linux内核可以对这些io访问按LBA进行合并和排序,这样磁头在移动时,可以“顺便”读出移动过程中的数据。

SATA等磁盘甚至在磁盘中内置了io排序来进一步提升性能,一般需要在主板中进行配置才能启动磁盘内置io排序。linux的io排序是根据LBA进行的,但LBA是一个一维线性地址,无法完全反应出二维的圆形磁盘,所以磁盘的内置io排序能达到更好的效果。

如何针对性优化:

io访问调度能大幅提升io性能,前提是应用层同时发起了足够的io访问供linux去调度。

怎样才能从应用层同时向内核发起多个io访问呢?

方案一是用aio_read异步发起多个文件读写请求。

方案二是使用磁盘线程池同时发起多个文件读写请求。

对我们的http正向代理来说,采用16个线程读写磁盘可以将性能提升到2.5倍左右。具体开多少个线程/进程,可以根据具体使用场景来决定。

小提示:

将文件句柄设置为非阻塞时,进程还是会睡眠等待磁盘io,非阻塞对于文件读写是不生效的。在正常情况下,读文件只会引入十几毫秒睡眠,所以不太明显;而在磁盘io极大时,读文件会引起十秒以上的进程睡眠。

预读取:

linux内核可以预测我们“将来的读请求”并提前将数据读取出来。通过预读取可以减少读io的次数,并且减小读请求的延时。

如何针对性优化:

预读取的预测准确率是有限的,与其依赖预读取,不如我们直接开一个较大的缓冲区,一次性将文件读出来再慢慢处理;尽量不要开一个较小的缓冲区,循环读文件/处理文件。

虽然说“预读取”和“延迟分配”能起到类似的作用,但是我们自己扩大读写缓冲区效果要更好。

延迟分配:

当文件扩大,需要分配磁盘空间时,可以不立即进行分配,而是暂存在内存中,将多次分配磁盘空间的请求聚合在一起后,再进行一次性分配。

延迟分配的目的也是减少分配次数,从而减少文件不连续。

延迟分配的副作用有几个:

1、如果应用程序每次写数据后都通过fsync等接口进行强制刷新,延迟分配将不起作用

2、延迟分配有可能间歇性引入一个较大的磁盘IO延时(因为要一次性向磁盘写入较多数据)

只有少数新文件系统支持这个特性

如何针对性优化:

如果不是对安全性(是否允许丢失)要求极高的数据,可以直接在应用程序里缓存起来,积累到一定大小再写入,效果比文件系统的延迟分配更好。如果对安全性要求极高,建议经常用fsync强制刷新。

在线磁盘碎片整理:

Ext4提供了一款碎片整理工具,叫e4defrag,主要包含三个功能:

1、让每个文件连续存储

2、尽量让每个目录下的文件连续存储

3、通过整理空闲磁盘空间,让接下来的分配更不容易产生碎片

如何针对性优化:

“让每个目录下的文件连续存储”是一个极有价值的功能。

传统的做法是通过拼接图片来将这10张图片合并到一张大图中,再由前端将大图切成10张小图。

有了e4defrag后,可以将需连续访问的文件放在同一个文件夹下,再定期使用e4defrag进行磁盘整理。

实现自己的文件系统:

在大部分服务器上,不需要支持“修改文件”这个功能。一旦文件创建好,就不能再做修改操作,只支持读取和删除。在这个前提下,我们可以消灭所有文件碎片,把磁盘io效率提升到理论极限。

有一个公式可以衡量磁盘io的效率:

磁盘利用率=传输时间/(平均寻道时间+传输时间)

如若满意,请点击回答右侧【采纳答案】,如若还有问题,请点击【追问】

~ O(∩_∩)O~

嵌入式Linux开发中的文件I/O是什么

嵌入式linux开发中的文件I/O就是对外设进行文件抽象,也就是认为一切外部设备都是文件,所有对外设的访问都通过文件方式。多任务就是用一个CPU执行多个任务,这个任务叫做进程或线程。

I/O输入/输出(Input/Output),分为IO设备和IO接口两个部分。

在POSIX兼容的系统上,例如Linux系统,I/O操作可以有多种方式,比如DIO(Direct I/O),AIO(Asynchronous I/O异步I/O),Memory-Mapped I/O(内存映设I/O)等,不同的I/O方式有不同的方式和性能,在不同的应用中可以按情况选择不同的I/O方式。

输入输出I/O流可以看成对字节或者包装后的字节的读取就是拿出来放进去双路切换;实现联动控制系统的弱电线路与被控设备的强电线路之间的转接、隔离,以防止强电窜入系统,保障系统的安全;

阅读剩余
THE END