linux操作系统作用:
1.通过驱动管理底层功能电路,即对底层的设备进行管理控制
2.操作系统有很丰富的系统调用接口,可以给顶层用户直接提供应用接口,提高开发效率。
linux的文件结构
在linux中,所有东西都可以看成是一个file。file是操作系统范畴的,是软件概念。操作系统里面的操作对象/管理对象就是file。顶层的用户要通过专门的接口(系统调用)操作file。
linux里有七种文件:
d:目录文件
-:普通文件
p:管道文件
l:链接文件
s:套接字文件
c:字符型设备文件
b:存储块型设备文件
linux的文件系统
Linux文件系统中的文件是数据的集合,文件系统不仅包含着文件中的数据而且还有文件系统的结构,所有Linux 用户和程序看到的文件、目录、软连接及文件保护信息等都存储在其中。
操作系统通过一个模块来管理文件系统,这个模块就是虚拟文件系统(VFS)。操作系统是虚拟的,他本身就是一段代码跑起来虚拟一个东西出来,所以操作系统里面的文件系统也是虚拟的。
而用户看到的是真实的文件系统,静态的文件系统。
相关函数
文件描述符:一个整数,他是一个索引值。当顶层用户的应用进程需要对底层的设备进行操作时,需要通过内核设备对应的文件打开,同时内核会将打开的文件封装成文件描述符返回给用户进程。如果应用进程需要对某个文件进行读写操作,就会将该文件的描述符作为参数传递给内核函数进行操作。
一般情况下,每启动一个进程的时候,内核会自动打开三个文件:
- 标准输入(键盘),对应的文件描述符是0,即宏stdiin
- 标准输出(屏幕),对应的文件描述符是1,即宏stdout
- 标准出错处理(屏幕),对应的文件描述符是2,即宏stderr
因此,如果我们创建了一个进程,打开了一个新的文件,文件描述符会从3开始。
说明:
- 描述符是相对一个进程来说的,每个进程都可以维护管理众多个描述符。
- 进程之间的描述符时独立的
- 进程创建后系统会自动创建三个描述符,分别是0,1,2
- 进程退出后,描述符会被系统自动回收
系统io操作
- open()函数:
作用:返回打开、创建的文件的文件描述符,打开成功返回文件描述符,打开失败则返回-1.
头文件:
#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:文件权限标志
(1) 打开已经存在的文件的权限标志:
O_RDONLY:只读打开
O_WRONLY:只写打开
O_RDWD:可读可写
如果要操作的文件不存在,则会报错。以上三个标志open函数只能选其一。
(2) 其他标志:可以与O_RDONLY、O_WRONLU、O_RDWD 位或使用
O_CREAT:若文件不存在,则创建文件。使用时可以和第三个参数mode一起使用
O_APPEND:每次对文件进行写操作时都追加到文件末端
O_TRUNC:若文件存在,且以只写或读写方式成功打开,则删除原文件全部数据。如果文件不存在,则操作失败
O_EXCL:测试文件是否存在,如果不存在,则创建该文件。如果和O_CREAT结合使用时文件已经存在,则会报错。 - mode_t mode:设置文件权限。最终权限mode = mode_t mode &~ 掩码
- close()函数
作用:关闭文件描述符指向的动态文件,并存储文件和刷新缓存。关闭成功返回0,失败返回-1
头文件:
#include <unistd.h>
原型:
int close(int fd);
参数说明:
int fd:文件描述符
- write()函数
作用:对文件进行写操作。成功返回写入的字节数(int),失败返回-1
头文件:
#include <unistd.h>
原型:
ssize_t write(int fd, const void *buf, size_t count);
参数说明:
- int fd:文件描述符
- const void * buf:要写入的数据地址
- size_t cout:写入数据的大小
- read()函数
作用:对文件进行读操作。成功返回读取的字节数(int),失败返回-1.
头文件
#include <unistd.h>
原型:
ssize_t read(int fd, void *buf, size_t count);
参数说明:
- int fd:文件描述符
- void *buf:读取的数据要存储的地址
- size_count:读取数据的大小
- access()函数
作用:检查调用进程是否可以对指定的文件执行某种操作。成功操作返回0,失败返回-1.
头文件
#include <unistd.h>
原型:
int access(const char *pathname, int mode);
参数说明:
- const char *pathname:文件路径
- int mode:文件权限
R_OK:读
W_OK:写
X_OK:执行
F_OK:测试文件是否存在
if(access(./hello.c,R_OK) == -1)
{
printf("can't read file.\n");
exit(-1);
}
- lseek()函数
作用:文件指针偏移函数。成功返回文件指针的偏移字节数,失败返回-1.
头文件
#include <sys/types.h>
#include <unistd.h>
原型:
off_t lseek(int fd, off_t offset, int whence);
参数说明:
- int fd:文件描述符
- off_t offset:相对基准点的偏移量。整数代表右偏移,负数代表左偏移,0代表不变
- int whence:基准点,有三个
SEEK_SET:文件头部
SEEK_CUR:当前位置
SEEK_END:文件末尾
最终文件指针的位置: whence + offset (基准点+偏移量)
示例代码:
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/types.h>
int main()
{
int fd;
int wr_cnt,rd_cnt;
char buffer[] = "hello world";
char rd_buffer[128] = {
0};
fd = open("./hello.c",O_RDWR|O_CREAT|O_APPEND);
if (fd < 0)
{
perror("open fail");
exit(-1);
}
wr_cnt = write(fd,buffer,sizeof(buffer));
printf("write count: %d\n",wr_cnt);
//因为write的时候,文件指针已经指向文件的结尾。因此读的时候要将文件指针移动到文件开头。
lseek