赞
踩
在linux系统中,“一切皆文件”这一观点非常重要,也就是说无论执行什么类型的操作,都可以用 “打开 open->读写 read/write->关闭 close”模式来操作。
大多数情况下,我们只需要使用五个基本的库函数——open、close、read、write和ioctl。
目录除了本身包含的内容外,还会有一个名字和一些属性,即“管理信息”,例如:利用ls -l在当前目录下执行,可以得到如下图所示
红色框线圈出的就是文件名字和对应文件属性。
硬件设备在linux操作系统中通常也被表示为文件。
在linux中比较重要的设备文件有三个——/dev/console、/dev/tty和dev/null。
/dev/console
这个设备代表的是系统控制台。错误信息和诊断信息通常会被发送到这个设备。
/dev/tty
如果一个进程有控制终端,那么特殊文件/dev/tty就是这个控制终端(键盘和显示屏,或键盘和窗口)的别名(逻辑设备)。
/dev/null
这是空(null)设备。所有写向这个设备的输出都将被丢弃。而读这个设备会立刻返回一个文件尾标志,所以在cp命令中可以把它用做拷贝空文件的源文件。
在输入输出操作中,直接使用底层系统调用会使效率非常低,所以linux/unix提供了一系列标准函数库,一般在<unistd.h>头文件中。
每个运行中的程序被称为进程,它有一些与之关联的文件描述符。可以通过他们访问打开的文件或设备。
当开始运行程序时,一般会有三个已经打开的文件描述符。
系统调用write的作用是,把缓冲区buf的前count个字节写入与文件描述符fildes关联的文件中。它返回实际写入的字节数。如果返回0,则表示未写出任何数据,如果是-1,则表示write调用出错,对应的错误代码保存在全局标量errono里面。
调用原型如下:(可以使用man 2 write在linux系统中查看write函数的帮助页)
#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t count);
来个demo试试:
#include <unistd.h>
#include <stdlib.h>
int main()
{
if(write(1, "Here is some data\n", 18) != 18) // 人为设定必须写入18个字节
write(2, "A write error has occurred on file descriptor 1\n", 46);
exit(1); // 与return 0;的作用一样
}
系统调用read的作用是,把缓冲区buf的前count个字节读入与文件描述符fildes关联的文件中。它返回实际读入的字节数。如果返回0,则表示未读出任何数据,如果是-1,则表示write调用出错,对应的错误代码保存在全局标量errono里面。
调用原型如下:(可以使用man 2 read在linux系统中查看read函数的帮助页)
#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);
来个demo试试:
#include <unistd.h> #include <stdlib.h> int main() { char buffer[20]; // 定义一个存储标准输入的缓冲区,大小为20个字节 int nread; // 存储read函数返回值 nread = read(0, buffer, 10); if(nread == -1) { write(2, "a read error!\n", 14); // 打印出读取错误 } if(write(1, buffer, nread) != nread) // 输出读取的字符串 write(2, "write error!\n", 13); // 输出错误 return 0; }
同样用man 2 open打开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, mode_t mode);
int creat(const char *pathname, mode_t mode);
打开文件成功返回0,否则返回-1,并设置全局变量errno以指明失败的原因。
需要说明的是,参数flags表示打开文件所采取的动作,而mode是表示文件的权限,也可以单独用chmod函数来设定。
下面介绍一下flags参数最常用的模式:
模式 | 说明 |
---|---|
O_RDONLY | 以只读方式打开 |
O_WRONLY | 以只写方式打开 |
O_RDWR | 以读写方式打开 |
O_APPEND | 把写入数据追加在文件的末尾 |
O_CREAT | 如果需要,就按参数mode给出的访问模式创建文件 |
O_EXCL | 与O_CREAT一起使用,确保调用者创建出文件。open是一个原子操作,也就是说,它只执行一个函数调用。使用这个可选模式可以防止两个程序同时创建一个文件,如果文件存在,open调用将失败 。 |
下面说一下参数mode,就不多解释,下图所示,输入对应的数字就好,当然也可以叠加,比如700表示所有者可以读写和执行。
close函数调用终止一个文件描述符fd与其对应文件之间的关联。
close调用成功就返回0,出错就返回-1.
#include <unistd.h>
int close(int fildes);
ioctl调用有点像是一个大袋子。它提供了一个用于控制设备及其描述符行为和配置底层服务的接口。
终端、文件描述符、套接字甚至磁带机都可以有为它们定义的ioctl。
#include <unistd.h>
int ioctl(int fd, int cmd, ...);
#include <sys/types.h>
#include <unistd.h>
off_t lseek(int fd, off_t offset, int whence);
其中offset表示偏移值,whence表示偏移值的用法,有SEEK_SET(绝对位置),SEEK_CUR(相对位置),SEEK_END(相对于文件尾的相对位置)
fstat、stat和lstat函数
返回与打开的文件描述符相关的文件状态信息,该信息将写到buf结构中。
详情请见man帮助页
dup和dup2函数
该函数调用提供了复制文件描述符的一种方法,是我们能够通过两个或者更多个不同的描述符来访问同一个文件。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。