OS
)提供给用户程序(APP
)调用的一组“特殊”接口,用户程序(APP
)可以通过这组“特殊”接口来获得操作系统内核(OS Kernel
)提供的服务。系统调用规定用户进程进入内核空间的具体位置,进行系统调用时,程序运行空间需要从用户空间进入内核空间,处理完后再返回用户空间
。进程控制
、进程间通信
、文件系统控制
、系统控制
、存储管理
、网络管理
、socket 控制
、用户管理
等几类。Soft Interrupt
)机制向内核提交请求(Request
),以获取内核(Kernel
)服务的接口。在实际使用中程序员调用的通常是用户编程接口。API
)遵循了在 UNIX 中最流行的应用编程界面标准 — POSIX 标准
,其是由 IEEE 和 ISO/IEC 共同开发的标准系统。该标准基于当时现有的 UNIX 实践和经验,描述了操作系统(OS
)的系统调用编程接口(即 API
),用于保证应用程序可以在源代码一级上在多种操作系统上移植运行
。这些系统调用编程接口主要是通过 C 库(libc)实现
的。
Portable Operating System Interface of UNIX
,缩写为 POSIX
)2.1.在 Linux 中对目录和设备的操作都等同于文件的操作,其极大的简化了系统对不同设备的处理,提高了效率。
2.2.Linux 中的文件主要分为 4 种:普通文件、目录文件、链接文件和设备文件(详细见章节文件系统)。
2.3.为了区分 Linux 中内核和引用特定的文件,采用文件描述符(fd
)这一概念,对于 Linux 而言,所有对设备和文件的操作都是使用文件描述符来进行的(即一切皆文件)。
2.4.文件描述符是一个非负的整数(fd>=0
),它是一个索引值,并指向在内核中每个进程打开文件的记录表。当打开一个现存文件或创建一个新文件时,内核就向进程返回一个文件描述符;当需要读写文件时,也需要把文件描述符作为参数传递给相应的函数。
2.5.一个进程启动时,都会打开 3 个文件:标准输入、标准输出 和 标准出错 处理。这 3 个文件分别对应文件描述符(fd)为: 0(STDIN_FILENO)、1(STDIN_FILENO) 和 2(STDERR_FILENO)。
文件I/O操作的系统调用,主要用到5个函数:open()、close()、read()、write() 和 lseek()。这些函数的特点是不带缓存,直接对文件(包括设备)进行读写操作。这些函数虽然不是 ANSI C 的组成部分,但是 POSIX 的组成部分。
open() 函数用于打开或创建文件,在打开或创建文件时可以指定文件的属性及用户的权限等各种参数
。
close() 函数用于关闭一个被打开的文件。当一个进程终止时,所有被它打开的文件都由内核自动关闭
,很多程序都使用这一功能而不显示地关闭一个文件。
read() 函数用于将从指定的文件描述符中读出的数据放到缓存区中,并返回实际读入的字节数
。若返回 0,则表示没有数据可读,即已达到文件尾。读操作从文件的当前指针位置开始。当从终端设备文件中读出数据时,通常一次最多读一行。
write() 函数用于向打开的文件写数据,写操作从文件的当前指针位置开始
。对磁盘文件进行写操作,若磁盘已满或超出该文件的长度,则 write()函数返回失败。
lseek() 函数用于在指定的文件描述符中将文件指针定位到相应的位置
。它只能用在可定位(可随机访问)文件操作中
。管道、套接字
和大部分字符设备文件
是不可定位
的,所以在这些文件的操作中无法使用
lseek()。
在文件已经共享的情况下,也就是当多个用户共同使用、操作一个文件的情况,此时在Linux中通常采用是给文件上锁,来避免共享的资源产生竞争的状态。
文件锁包括 建议性锁 和 强制性锁 。
要求每个上锁文件的进程都要检查是否有锁存在,并且尊重已有的锁
。在一般情况下,内核和系统都不使用建议性锁
。由内核执行的锁,当一个文件被上锁进行写入操作的时候,内核将阻止其他任何文件对其进行读写操作
。
在Linux中,实现文件上锁的函数有 lockf() 和 fcntl(),其中 lockf() 用于对文件施加建议性锁,
而 fcntl() 不仅可以施加建议性锁,还可以施加强制锁。同时 fcntl() 还能对文件的某一记录上锁,也就是 记录锁。
能够使多个进程都能在文件的同一部分建立读取锁
。在任何时刻只能有一个进程在文件的某个部分上建立写入锁
。当然,在文件的同一部分不能同时建立读取锁和写入锁
。参考文献:《Linux嵌入式应用程序开发标准教程》