【Linux C/C++】 第06讲 文件IO

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Nanhu2012/article/details/50613914

一 IO的基础

     1.1 认识内核对象

             Linux不允许直接访问内核设备和内存,但可以通过内核系统函数去访问

             对每个内核对象进行编号ID

             如果访问内核对象,只能通过内核ID

             编程模型:

                   申请得到一个内核ID

                   在内核系统函数中使用内核ID得到对应的内核对象数据


       1.2 怎么访问文件

              使用函数,传递一个文件名,系统打开文件,加载文件至内核,返回一个内核ID

扫描二维码关注公众号,回复: 3595374 查看本文章

              使用函数,传递内核ID,得到数据

              使用函数,传递内核ID,告诉系统释放文件


               ID:文件描述符,file description(fd)

     1.3 每个程序默认打开三个文件设备:

                 0:标准输入

                 1:标准输出

                 2:错误输出

      1.4 操作文件描述符

              ssize_t write(int fd,

                       void* buf,//要写入内核对象的数据

                       size_t size);//写入数据的大小

              返回:

                      > 0 实际写入的数据

                         -1 写入错误

             ssize_t  read(int fd,

                                 void* buf,//返回数据的空间

                                  size_t size);//空间大小

               返回:

                        > 0 实际读取的数据

                        = 0 碰到文件结束符号 EOF

                          -1 读取错误


二  基于文件的描述符

      2.1  获取/释放文件描述符

                 a.文件类型

                       目录文件d

                       普通文件f

                       字符设备文件c

                       块设备文件b  (/dev/sda 硬盘)

                       软连接文件l 

                       管道文件p

                       socket文件s

                  b.文件属性

                        

       2.2 通过文件描述符读写各种数据

                    

       2.3 文件描述符与重定向

                   

三 IO与文件映射

       3.1 IO的共享与效率

              read与write其中数据缓冲的大小

              读取数据的缓冲:getpagesize

       3.2 定位与定位读取

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

              lseek改变读取位置

              pread/pwrite 在指定的位置读写数据,改变读写位置

              pread == lseek + read

              pwrite == lseek + write

        3.3 文件的其他操作

               fstat 获取文件状态

               ftruncate 改变文件大小

         3.4 文件映射

               虚拟地址映射到内存

               虚拟地址可以映射到文件:可以用内存的方式读写文件

               mmap/munmap

                案例:

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

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


四 文件描述符的操作(IO锁)

            文件描述符是整数

            文件描述符对应内核的上下文

            4.1 dup dup2 拷贝文件描述符

            4.2 fcntl对文件描述符的属性的修改

                  4.2.1 拷贝文件描述符

                  4.2.2 修改判定文件的描述标记

                  4.2.3 修改判定文件的状态标记

                                   不可修改 O_RDONLY O_WRONLY O_RDWR O_CREAT O_EXCL

                                    可修改 O_APPEND O_ASYN异步方式

                  4.2.4 设置强制锁 (重新编译内核)

                  4.2.5 设置建议锁(默认)

                  4.2.6 设置IO的信号


      文件IO实例:

          socket_server_send是对send函数的一个封装,读者可以自行实现

//读取指定文件并传送到客户端
void SendFile(const char* filename,int conn_id)
{
	int fd=0;
	char path[256]={0};
	int loc=0;

	sprintf(path,"./file/%s",filename);

	fd = open(path,O_RDONLY);
	if(-1 == fd)
	{
		printf("FileManager::SendFile open error\n");
		return ;
	}

	struct stat info;
	fstat(fd,&info);
	printf("file %s size is %d\n",filename,info.st_size);

	short total_size = 4;
	total_size += sizeof(int);
	total_size += strlen(filename);

	short package_size = total_size - 2;
	char* buf = (char*)malloc(total_size);
	memcpy(buf,&package_size,2);
	char type='F';
	memcpy(buf+2,&type,1);
	char extra = 0;
	memcpy(buf+3,&extra,1);
	int file_size = info.st_size;
	memcpy(buf+4,&file_size,4);
	memcpy(buf+8,filename,strlen(filename));
	
	printf("total_size:%d\n",total_size);
	socket_server_send(ss,conn_id,buf,total_size);
	
	char buffer[2048]={0};
	while(1)
	{
		lseek(fd,loc,SEEK_SET);
		
		short size = read(fd,buffer,1024);
		if(-1 == size)
		{
			printf("file_manager: file read error\n");
			break;
		}
		else if(0 == size)
		{
			printf("file_manager: file send over!\n");
			break;
		}
		printf("file send package size:%d\n",size);
		loc += size;

		total_size = size+4;
		buf = (char*)malloc(total_size);
		package_size = total_size-2;
		memcpy(buf,&package_size,2);
		memcpy(buf+2,&type,1);
		extra = 1;
		memcpy(buf+3,&extra,1);
		memcpy(buf+4,buffer,size);
	
		socket_server_send(ss,conn_id,buf,total_size);
	}
	
	close(fd);	
}


猜你喜欢

转载自blog.csdn.net/Nanhu2012/article/details/50613914