linux文件系统open,read,lseek,stat,mmap函数介绍

函数open(),create(),lseek()介绍

  1. 函数原型:
    int open(const char* pathname, int falgs);
    int create(const char* pathname, int falgs);
    int open(const char* pathname, int flags, mode_t mode);
    int create(const char* pathname, int flags, mode_t mode);
  2. 包含头文件
    sys/types.h,sys/stat.h和fcntl.h;
  3. 返回值
    正常返回文件的描述值,错误返回-1;
  4. flags
    必选:
    O_RDONLY,O_WRONLY,O_RDWR
    可选:
    O_APPEND 追加
    O_CREAT 不存在则创建,mode需要设置!
    O_EXCL 查看文件是否存在,如果同时指定了O_CREAT,而文件已经存在在则返回错误。用这种方法可以安全打开文件
    O_TRUNC 将文件长度截断为0,通常用于对需要清空的文件进行归零操作
  5. mode
    结合O_CREAT使用,否则无效
    读写执行权限:
    S_IRWXU(G\O) U(G\O)分别代表user、group、other
    读或写或执行权限
    S_IR(W\X)USR(GRP\OTH) R(W\X)分别代表读写执行,USR(GRP\OTH)分别代表user、group、other
  6. 示例
/*open_test.c 打开文件的例子*/
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<stdio.h>

int main(void)
{
	int fd = -1;
	char filename[] = "test.txt";
	fd = open(filename,O_RDWR);
	if(fd>-1)
	{
		printf("Open file %s success,fd:%d\n",filename,fd);
	}
	else
	{
		printf("Open file %s failure!\n",filename);
	}

	return 0;
}
  1. 执行结果
$ ll
总用量 5
drwxrwxrwx 1 zhujun zhujun  256 10月  4 18:54 ./
drwxrwxrwx 1 zhujun zhujun  360 10月  4 18:23 ../
-rwxrwxrwx 1 zhujun zhujun  638 10月  4 18:54 open_test.c*
$ gcc -o open1 open_test.c
$ ./open1
Open file test.txt failure!
$ echo "">test.txt
$ ./open1
Open file test.txt success,fd:3

关闭文件函数close()

头文件unistd.h
int close(int fd);

读取文件read()函数

  1. 依赖头文件unistd.h
  2. 函数原型
    ssize_t read(int fd, void* buf, size_t count);
    从文件描述符fd对应的文件中读取count字节,放到buf开始的缓冲区中,如果count=0,则返回0,不进行其他操作;如果count大雨SSIZE_MAX,则结果不可预料。读取成功的时候,文件对应的读取位置指针,向后移动位置,大小为成功读取的子节成功则返回字节数,失败返回-1,文件末尾返回0。 返回值类型为ssize,具体实现时可以定义为long或者int
  3. 示例
/* 文件read_test.c */
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
#include<stdio.h>

int main(void)
{
	int fd = -1;
	ssize_t size = -1;
	char buff[10];
	char filename[] = "test.txt";

	fd = open(filename, O_RDONLY);
	if(fd<0)
	{
		printf("Open file %s failure\n",filename);
	}
	else
	{
		printf("Open file %s success,fd %d\n",filename,fd);
	}
	while(size)
	{
		size = read(fd, buff, 10);
		if(size == -1)
		{
			close(fd);
			printf("Read file error occurs.\n");
			return -1;
		}
		else
		{
			if(size>0)
			{
				printf("Read %d bytes:",size);
				printf("\"");
				for(int i=0;i<size;i++)
					printf("%c",*(buff+i));
				printf("\"\n");
			}
			else
			{
				printf("Reach EOF.\n");
			}
		}
	}
	return 0;

}

test.txt 文件内容:

This is a test file to test if read function could run well.
  1. 运行结果
$ gcc -o rt read_test.c
read_test.c: In function ‘main’:
read_test.c:29:37: warning: format ‘%ld’ expects argument of type ‘long int’, but argument 3 has type ‘int’ [-Wformat=]
   printf("Open file %s success,fd %ld\n",filename,fd);
                                   ~~^
                                   %d
read_test.c:44:19: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘ssize_t {aka long int}[-Wformat=]
     printf("Read %d bytes:",size);
                  ~^
                  %ld
$ ./rt
Open file test.txt success,fd 3
Read 10 bytes:"This is a "
Read 10 bytes:"test file "
Read 10 bytes:"to test if"
Read 10 bytes:" read func"
Read 10 bytes:"tion could"
Read 10 bytes:" run well."
Read 1 bytes:"
"
Reach EOF.

lseek()函数

  1. 函数原型:
	#include<sys/types.h>
	#include<unistd.h>
	off_t lseek(int fd, off_t offset, int whence);
  1. 描述:
    对文件描述符fd对应的文件,按照模式whence和相对偏移量offset,重新设置文件的偏移量。返回新的偏移量(成功),失败返回-1。
    whence表示操作模式,offset表示相对偏移量
    whence:
    SEEK_SET文件起始位置
    SEEK_CUR当前偏移位置
    SEEK_END文件末尾

    off_t cur_pos = lseek(fd, 0, SEEK_CUR)可以获得当前的偏移量,也可以校验当前设备是否支持lssek函数。

  2. 示例

/* lseek_test.c */
#include<sys/types.h>
#include<sys/stat.h>
#include<unistd.h>
#include<fcntl.h>
#include<stdio.h>

int main(void)
{
	off_t offset = -1;
	offset = lseek(1, 0, SEEK_CUR);/*将标准输入文件描述符的文件偏移量设为当前值*/
	/* 0,1,2描述符分配给系统,0:标准输入;1:标准输出;2:标准错误*/
	if(offset == -1)
	{

		printf("STDOUT can`t seek\n");
		return -1;
	}
	else
	{
		printf("STDOUT can seek\n");
	}
	return 0;
}
  1. 结果
$ gcc -o lsek lseek_test.c
$ ./lsek
STDOUT can`t seek

获得文件状态fstat函数

  1. 文件状态:文件大小、权限、修改时间
  2. stat(), fstat(), lstat()可以获得文件的状态
  3. 函数原型:
#include<sys/types.h>
#include<sys/stat.h>
#include<unistd.h>
int stat(const char* path, struct stat * buf);
int fstat(int fd, struct stat * buf);
int lstat(const char* path, struct stat *buf);
  1. 描述:成功时返回0;失败时返回-1
  2. struct stat结构:
struct stat
{
	dev_t		st_dev;		/*此文件所处设备的设备ID号*/
	ino_t		st_ino;		/*inode数值*/
	mode_t		st_mode;	/*保护设置*/
	nlink_t		st_nlink;	/*硬连接数*/
	uid_t		st_uid;		/*文件所有者的ID*/
	gid_t		st_gid;		/*文件所有者的组的ID*/
	dev_t		st_rdev;	/*以字节计算的大小*/
	blksize_t	st_blksize;	/*文件系统的块大小*/
	blkcnt_t	st_blocks;	/*占用的块的数量*/
	time_t		st_atime;	/*最后方位时间*/
	time_t		st_mtime;	/*最后修改时间*/
	time_t		st_ctime;   /*最后状态改变时间*/
}

文件空间映射函数mmap

  1. 函数原型:
#include<sys/mman.h>
void* mmap(void * start, size_t length, int prot, int flags, int fd, off_t offset);
  1. 描述:
    将文件或者设备空间映射到内存中,可以通过对映射后的内存空间存取来获得存取文件一致的控制方式,不必使用read、write函数。简单来说就是将文件映射到内存中的某一段,映射到的内存不占用空间,仅仅占用一段地址空间。
    将描述符fd对应的文件,自offset开始的一段长为length的数据映射到内存中,用户可以设定映射的内存地址,但是具体映射到内存的位置由返回值确定。当映射成功后,返回映射到的内存地质。如果失败返回值为(void *)-1。通过errno获得错误方式。
    start 指定要映射到的地址,通常为NULL
    prot 表示映射区保护方式,是一个组合值,可以是一个或者多个
    描述
    PROT_EXEC可执行
    PROT_READ可读
    PROT_WRITE可写
    PROT_NONE不能存取
    当然这个设置会受到打开文件的限制,权限不能超过打开文件的权限,超过则对应的权限失效。
    flags 设定映射对象的类型、选项和是否可以对映射对象进行操作,也是一个组合值
    描述
    MAP_FIXED如果设置了start,而无法映射到所指的地址,则映射失败
    MAP_SHARED共享映射区域,映射区域允许其他进程共享,对映射区域写入数据将会写入到原文件中
    MAP_PRIVATE对映射区域的修改不会写入原文件
    MAP_ANONYMOUS建立匿名映射。此时忽略参数fd,不涉及文件,而且映射区无法和其他进程共享
    MAP_DENYWRITE禁止文件写入操作,只能通过对映射区操作的方式实现对文件的操作,不允许直接操作文件
    MAP_LOCKED将映射区锁定,此区域不会被虚拟内存重置

MAP_PRIVATE,MAP_SHARED必须选其一。shared表示多个进程使用一个内存映射的副本,任何进程都可以对此映射区进行修改,而且修改可见。private表示多个进程之间的副本不一致,写入操作之后,会复制一个副本给修改的进程。

munmap函数 取消mmap函数的映射关系

  1. 原型
#include<sys/mman.h>
int munmap(void* start, size_t length);
  1. 描述:
    start为mmap函数的返回值,即映射的内存地址,length为映射长度
  2. 编程模式:
/*打开文件*/
fd = open(filename, flags, mode);
if(fd<0)
	...(error);
ptr = mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
/*对文件进行操作*/
...
/*取消映射关系*/
numap(ptr, len);
/*关闭文件*/
close(fd);
  1. 示例
#include<sys/stat.h>
#include<sys/types.h>
#include<fcntl.h>
#include<unistd.h>
#include<sys/mman.h>
#include<string.h>
#include<stdio.h>

#define FILELENGTH 80

int main(void)
{
	int fd  = -1;
	char buf[] = "quick brown fox jumps over the lazy dog";
	char* ptr = NULL;
	/*打开文件,并将文件长度缩短为0,不存在则创建,权限为可读可写可执行*/
	fd = open("mmap.txt", O_RDWR|O_CREAT|O_TRUNC, S_IRWXU);
	if(fd == -1) return -1;

	/*将文件长度扩展为80,向后偏移文件的偏移量到79*/
	lseek(fd, FILELENGTH-1, SEEK_SET);
	write(fd, "a", 1);/*随意写入一个字符*/
	/*将文件mmap.txt中的数据从开头到1M的数据映射到内存中,对文件操作立即显示在文件上,可读写*/
	ptr = (char*)mmap(NULL, FILELENGTH, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
	if((char*)-1 == ptr )
	{
		printf("mmap failure\n");
		close(fd);
		return -1;

	}
	/*将buf中的字符串复制到映射区域中,起始位置为ptr+16*/
	memcpy(ptr+16, buf, strlen(buf));
	munmap(ptr, FILELENGTH);
	close(fd);
	return 0;
}
  1. 运行结果
$ gcc -o mapt mmap_test.c 
$ ./mapt 
$ ll
总用量 82
drwxrwxrwx 1 zhujun zhujun  4096 105 16:07 ./
drwxrwxrwx 1 zhujun zhujun  4096 104 18:23 ../
-rwxrwxrwx 1 zhujun zhujun  8704 105 16:07 mapt*
-rwxrwxrwx 1 zhujun zhujun  1347 105 16:06 mmap_test.c*
-rwxrwxrwx 1 zhujun zhujun    80 105 16:07 mmap.txt*
$ od -c mmap.txt
0000000  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0
0000020   q   u   i   c   k       b   r   o   w   n       f   o   x    
0000040   j   u   m   p   s       o   v   e   r       t   h   e       l
0000060   a   z   y       d   o   g  \0  \0  \0  \0  \0  \0  \0  \0  \0
0000100  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0   a
0000120
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值