4-IO文件映射_文件描述符

一. IO与映射

     1. IO 的共享 与 效率
             read  与  write  其中数据缓冲的大小
              读取数据的缓冲: getpagesize。
     2. 定位与定位读取  (随机读取)

   read 与 write 在操作的时候,自动移动读取位置。

   2.1   lseek 改变读取位置。

       #include <sys/types.h>
       #include <unistd.h>


       off_t lseek( int fd,    // 定位文件描述符号

       off_t offset,    // 定位位置

       int whence);   // 定位参照点:文件开始位置/ 文件结束位置/文件结束位置

  返回值: 成功返回文件的偏移量,出错返回-1

  三个符号常量 SEEK_SET ,SEEK_CUR  SEEK_END



/// lseek.c
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>

main()
{
	int fd;
	float score;
	
	int r;
	int i = 0;
	
	fd = open("stu.dat",O_RDONLY);
	if(fd== -1)printf("open error:%m\n"),exit(-1);
	//定位
	for(i=0;i<2; ++i)
	{
		r = lseek(fd,i*28,SEEK_SET);
		r = lseek(fd,24,SEEK_CUR);
		// r = lseek(fd,i*28+24,SEEK_SET); // 等同上面两句
		// 读取
		r = read(fd,&score,sizeof(float));
		//打印, 输出
		printf("%.2f\n",score);
	}
	close(fd);
}

 

     2.2   lseek 的作用: 定位文件的位置

    lseek 移动位置只要合法,都为有效。

 2.3  lseek + write = pwrite

             lseek + read = pread


for(i=0; i<2; i++)
{
   pread(fd,&score,sizeof(float),i*28 +24);
   printf("%.2f\n",score);
}

2.4  案例 

   读取一个特殊文件:

       /proc/${pid}/mem 文件  程序的虚拟文件内存文件


/// demo1.c
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>

int a= 9999;
main()
{
	char filename[100];
	int fd;
	int data = 88;
	
	// 得到文件名
	sprintf(filename,"/proc/%d/mem",getpid());
	// 打开文件
	fd = open(filename,O_RDWR);
	if(fd == -1) printf("open error:%m\n"),exit(-1);
	// 读取a地址这个位置的数据
	pread(fd,&data,4,(int)&a);
	printf("%d\n",a);
	
	pwrite(fd,&data,4,(int)&a);
	printf("%d\n",a);
	
	close(fd);
}

3. 文件的其他操作(返回与此命令有关的信息)

   fstat  获取文件的状态

   ftruncate 改变文件的大小

------------

stat  main  获取main文件的信息

------------


// fstat.c

#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>

main()
{
	int fd;
	struct stat st;
	fd = open("stu.dat",O_RDONLY); // 只读方式打开
	if(fd == -1) printf("err:%m\n"),exit(-1);
	/// 获取文件状态
	fstat(fd,&st);
	// 打印数据大小,数据权限
	printf("%ld,%o\n",st.st_size,st.st_mode);
	close(fd);
}

4. 文件映射:

        虚拟地址映射到内存。

        虚拟地址可以映射到文件:可以用内存方式访问文件。

        mmap / munmap(内存映射)

  作用: 建立一段可以被两个或者更多个程序读写的内存。一个程序对它所作的修给可以被其他程序可见。

    mmap 函数创建一个指向一段内存区域的指针,该内存区域 与 可以通过一个打开的文件描述符访问的文件的内容相关联

       #include <sys/mman.h>

       void *mmap(void *addr, // 如果该值为0,结果指针就将自动分配

       size_t length,

       int prot, // 用于设置内存段的访问权限

       int flags, // 控制程序对该内存段的改变所造成的影响
                    int fd,

       off_t  offset); // 改变经共享内存段访问的文件中数据的起始偏移量
       int munmap(void *addr, size_t length);



prot 参数:

  PROT_READ: 允许读该内存段

       PROT_WRITE: 允许写该内存段

       PROT_EXEC:  允许执行该内存段

       PROT_NONE:  该内存段不能被访问

flags 参数:

   MAP_PRIVATE: 内存段是私用的,对它的修改只对本进程有效

          MAP_SHARED: 把对该内存段的修改保存到磁盘文件中

           MAP_FIXED:  该内存必须位于addr指定的位置

         案例:

     1. 使用内存方式写入数据

     2. 使用内存方式读写数据


// map_write.c

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <string.h>
#include <sys/mman.h>

struct stu
{
	char name[20];
	int age;
	float score;
};

main()
{
	int fd;
	struct stu *s; /// 文件在虚拟内存的映射首地址
	struct stat st;
	int size;  // 文件大小
	int count; //  记录条数
	int i;
	//1. 打开文件
	fd = open("newstu.dat",O_RDWR | O_CREAT | O_EXCL,0666);
	if(fd == -1) // 如果文件存在,打开文件
	{
		fd = open("newstu.dat",O_RDWR);
		if(fd == -1) printf("::%m\n"),exit(-1);
	}
	//2. 得到文件大小,文件记录数
	fstat(fd,&st);
	size = st.st_size;
	count = size / sizeof(struct stu);
	//3.改变文件大小,文件大小改变只要在munmp之前都有成效
	ftruncate(fd,size + sizeof(struct stu));
	//4.映射到一个虚拟地址
	s = mmap(0,size + sizeof(struct stu),
	       PROT_READ | PROT_WRITE,MAP_SHARED,fd,0);
	//5. 把数据写入虚拟地址
	printf("输入姓名:");
	scanf("%s",s[count].name);
	printf("输入年龄:");
	scanf("%d",&s[count].age);
	printf("输入成绩:");
	scanf("%f",&s[count].score);
	
	// 打印输入的信息
	for(i=0; i<count;++i)
		printf("%s,\t%d,\t%.2f\n",s[i].name,s[i].age,s[i].score);
	
	//6. 卸载虚拟地址
	  munmap(s,sizeof(struct stu)+size);
	//7. 关闭文件
	close(fd);
	
		
}


————————————————————————
$ make
$ main
$ ls
$ ls -l newstu.dat
$cat newstu.dat
-------------------------------------

二.  文件描述符号的操作(IO锁)

  文件描述符号是整数。文件描述符号对应内核上下文环境。

  1.dup dup2  拷贝文件描述的属性的修改

    dup 拷贝文件描述符号,返回系统指定的整数。

    dup2拷贝文件描述符号,返回用户指定的整数。

       #include <unistd.h>

       int dup(int oldfd);
       int dup2(int oldfd, int newfd);
              返回值:成功则返回新的文件描述符,出错返回-1

 2. fcntl   对文件描述符号的属性的修改

       #include <unistd.h>
       #include <fcntl.h>

       int fcntl(int fd, int cmd, ... /* arg */ );

fcntl 函数有5种功能

     (1)复制一个现有的描述符号(cmd = F_DUPFD).

              (2)获取/设置文件描述符号标记(cmd = F_GETFD  或 F_SETFD)

     (3) 获取/设置文件状态标记(cmd = F_GETFL  ,或F_SETFL)

     (4)获得/设置异步I/O所有权(cmd = F_GETOWN ,或F_SETOWN)  

                   (5)获取/设置记录锁(cmd = F_GETLK, F_SETLK, 或F_SETLKW)






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值