Linux下文件操作

1.基于文件指针的文件操作
Linux的文件和文件描述符
Linux中对目录和设备的操作都是文件操作
普通文件:磁盘文件,能够进行随机的数据存储
管道:通信
目录:目录文件
设备:字符型设备和块设备
链接:套接字
fopen以mode的方式打开或创建文件,如果成功,将返回一个文件指针,失败则返回NULL,fopen创建的文件的访问权限将以0666与当前的umask结合来确定,不能指定权限。
在LInux系统中,mode里面的'b'(二进制)可以去掉,但是为了保持与其他系统的兼容性,建议不要去掉。ab和a+b为追加模式,在此两种模式下,无论文件读写点定位到何处,在写数据时都将是在文件末尾添加,所以比较适合于多进程写同一个文件的情况下保证数据的完整性。
rb 可读不可写
rb+ 可读可写
wb 不可读可写
wb+ 可读可写
ab 不可读可写
ab +可读可写
int sprintf(char *str,const char *format,...);字符串拼接函数
int atoi(const char *str);将字符串str转换成一个整数并返回结果
int sscnaf(char *str,const char *format,...);格式化输入
fprintf将格式化
目录操作
chomod:改变目录或文件的访问权限
绝对路径: /home/luke
相对路径:..当前目录
0777:0 111 111 111 八进制
获取改变当前目录:
char *getcwd(char *buf, size_t size);//获取当前目录相当于pwd
int chdir(const char *path);//修改当前目录,即切换目录,相当于cd
参数size为buf的空间的大小,buf所指的内存空间要足够大
chdir()函数:用来将当前的工作目录改变成以参数path所指的目录
创建和删除目录:
int mkdre(const char *pathname,mode_t mode);//创建目录,mode是目录权限
int rmdir(const char *pathname);//删除目录
获取目录信息:
#include<dirent.h>
DIR *opendir(const char *name);//打开一个目录
struct dirent *readdir(DIR *dir);//读取目录的一项信息。并返回该项信息的结构体指针
void rewinddir(DIR *dir);//重新定位到目录文件的头部
void seekdir(DIR *dir);//用来设置目录流当前的读取位置
off_t telldir(DIR *dir);//返回目录流当前的读取位置
int closedir(DIR *dir);//关闭目录文件
读取目录信息的步骤为:
用opendir函数打开目录
使用readdir函数迭代读取目录的内容,如果已经读取到目录末尾,又想重新开始读,则可以使用rewinddir函数将文件指针重新定位到目录文件的起始位置
用closedir函数关闭目录
一个文件名和一个inode对应
int stat(const char *pathname,struct stat *buf);//获取文件状态
unsigned short :mode_t st_mode;//文件类型
nlink_t st_nlink;//链接数
off_t st_size;//文件大小
blksize_t st_blksize;//块大小
基于文件描述符的文件操作(非缓冲)
1.文件描述符:
内核为每个进程维护一个已打开文件的记录表,文件描述符是一个较小的正整数,它代表记录表的一项,通过文件描述符和一组基于文件描述符的文件操作函数,就可以实现对文件的读、写、创建、删除等操作。
常用基于文件描述符的函数有open(打开)、create(创建)、close(关闭)、read(读取)、fstat(获取文件状态)、fchomod(权限)、flock(加锁)、fcntl(控制文件属性)、dup(复制)
2.打开创建和关闭文件
int open(const char *pathname,int flags,mode_t mode);//文件名 打开方式 权限
O_RDONLY 以只读方式打开
O_WRONLY以只写的方式打开
O_RDWR 以读写的方式打开
O_CREAT 如果文件不存在,则创建文件
O_APPEND 以追加方式打开文件,每次调用write时,文件指针自动先移到文件尾,用于多进程写同一个文件的情况
O_NONBLOCK 非阻塞方式打开,无论有无数据读取或等待,都会立即返回进程中
O_NODELAY 非阻塞方式打开
O_SYNC 同步打开文件
通常采用直接赋数值的形式
int fd=open("1.txt",O_WRONLY|O_CREATE,0755);
if(-1==fd)
{
perror("open failed!\n");
exit(-1);
}
linux中基于文件描述符的open函数,对于一个不存在的文件,不能通过O_WRONLY的方式打开,必须加上O_CREAT选项
close用于文件的关闭
int close(int fd);//fd表示文件描述词,是先前由open或creat创建文件时的返回值,文件使用完毕后,应该调用close关闭它,一旦调用close,则该进程对文件所加的锁全部都被释放,并且使文件的打开引用计数减一,只有文件的打开引用计数变为0之后,文件才会被真正的关闭
3.读写文件
ssize_t read(int fd,void *buf,size_t count);//文件描述词 缓冲区 长度
ssize_t write(int fd,const void *buf,size_t count);
对于read和write函数,出错返回-1读取完了之后,返回0,其他情况返回读写个数
4.改变文件大小
int ftruncate(int fd,off_t length);
函数ftruntrate会将参数fd指定的文件大小改为参数length指定的大小
参数fd为已打开的文件描述词,而且必须是以写入模式打开的文件。如果原来文件大小比参数length大,则超过的部分则会被删除
#include "func.h"

int main(int argc,char * argv[])
{
	if(argc!=2)
	{
		printf("error args\n");
		return -1;
	}
	int fd;
	fd=open(argv[1],O_RDWR|O_CREAT,0666);
	if(-1==fd)
	{
		perror("open");
		return -1;
	}
	int ret;
	ret=ftruncate(fd,1<<20);
	if(ret!=0)
	{
		perror("ftruncate");
		return -1;
	}
	close(fd);
	return 0;
}
#include 
    
    
     
     
#include 
     
     
      
      
#include 
      
      
       
       
#include 
       
       
        
        
#include 
        
        
          #include 
         
           #include 
          
            #include 
           
             #include 
            
              #include 
             
               #include 
              
                #include "func.h" int main(int argc,char * argv[]) { if(argc!=2) { printf("error args\n"); return -1; } int fd; fd=open(argv[1],O_RDWR|O_CREAT,0666); if(-1==fd) { perror("open"); return -1; } int ret; char *p; p=(char*)mmap(NULL,6,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0); if(p==(char*)-1) { perror("mmap"); return -1; } printf("p[0]=%c\n",p[0]); p[0]='H'; ret=munmap(p,6); if(-1==ret) { perror("munmap"); return -1; } close(fd); return 0; } 
               
              
             
            
           
          
        
       
       
      
      
     
     
    
    

5.文件定位
off_t lseek(int fd,off_t offset,int whence);//fd文件描述词
whence 可以是下面三个常量的一个
SEEK_SET 从文件头开始计算
SEEK_CUR 从当前指针开始计算
SEEK_END 从文件尾开始计算
6.获取文件信息
int stat(const char *file_name,stuct stat *buf);//文件名 stat结构体指针
int fstat(int fd,struct stat *buf);//文件描述词 state结构体指针
结构体stat的定义为:
struct stat{
dev_t st_dev; //如果是设备,返回设备表述符
ino_t st_ino;//i结点号
mode_t st_mode;//文件类型
nlink_t st_nlink;//链接数
uid_t st_uid;//属主ID
gid_t st_gid;//组ID
off_t st_size;//文件大小,字节表示
time_t st_atime;//最后访问时间
time_t st_mtime;//最后修改时间
time_t st_ctime;//最后权限修改时间
};
7.文件描述符的复制
系 统 调 用 函 数 dup 和 dup2 可 以 实 现 文 件 描 述 符 的 复 制 , 经 常用 来 重 定 向 进 程 的stdin(0),stdout(1),stderr(2)。
dup 返回新的文件描述符( 没有使用的文件描述符的最小编号)
int dup(int oldfd);
int dup2(int oldfd,int newfd);
文件描述符的复制是指用另外一个文件描述符指向同一个打开的文件,它完全不同于直接给文件描述符变量赋值
8.I/O多路转接模型
mkfifo 创建管道文件 管道文件用于进程间通信 全双工,半双工,单工
管道是半双工
1.管道读端和写端都打开后,程序才会往下执行
2.read端会阻塞
3.write端不会阻塞
#include 
     
     
      
      
#include 
      
      
       
       
#include 
       
       
        
        
#include 
        
        
         
         
#include 
         
         
           #include 
          
            #include 
           
             #include 
            
              #include "func.h" int main(int argc,char *argv[]) { if(argc!=3) { printf("error args\n"); return -1; } int fdr,fdw; fdr=open(argv[1],O_RDONLY);//打开管道1的读端 if(-1==fdr) { perror("open"); return -1; } fdw=open(argv[2],O_WRONLY);//打开管道2的写端 if(-1==fdw) { perror("open1"); return -1; } printf("open pipe success\n"); char buf[20]={0}; while(1) { memset(buf,0,sizeof(buf)); if(read(fdr,buf,sizeof(buf)-1)>0) { puts(buf); }else{ break; } memset(buf,0,sizeof(buf)); if(read(STDIN_FILENO,buf,sizeof(buf))>0) { write(fdw,buf,strlen(buf)-1); }else{ break; } } close(fdr); return 0; } #include "func.h" int main(int argc,char *argv[]) { if(argc!=3) { printf("error args\n"); return -1; } int fdw,fdr; fdw=open(argv[1],O_WRONLY);//打开1号管道的写端 if(-1==fdw) { perror("open"); return -1; } fdr=open(argv[2],O_RDONLY);//打开2号管道的读端 if(-1==fdr) { perror("open1"); return -1; } printf("process 2 open pipe success\n"); char buf[20]; while(1) { memset(buf,0,sizeof(buf)); if(read(STDIN_FILENO,buf,sizeof(buf))>0) { write(fdw,buf,strlen(buf)-1);//写到对端 }else{ break; } memset(buf,0,sizeof(buf)); if(read(fdr,buf,sizeof(buf)-1)>0) { puts(buf); }else{ break; } } return 0; } #include "func.h" int main() { sleep(5); char buf[20]={0}; read(0,buf,sizeof(buf)); puts(buf); return 0; } 
             
            
           
         
        
        
       
       
      
      
     
     

断开
1、写端断开,read返回值=0
Ctrl+d 结束输入
死锁
fd_set readset 轮巡监控事件 传入传出参数
int select(int,maxfd,fd_set*readset,fd_set*writre,fd_set*exceptionset,const struct timeval * timeout);
maxfd:最大的文件描述符(其值应该为最大的文件描述符字+1)
readset:内核读操作的操作符字集合
writeset:内核写操作的描述符字集合
exceptionset:内核异常操作的描述符字集合
timeout:等待描述符就绪需要多少时间。NULL代表永远等下去,一个固定值代表等待固定时间,0代表根本不等待,检查描述字之后立即返回
select 多路复用,监控描述符是否可读,避免阻塞
select 时间
#include 
     
     
      
      
#include 
      
      
       
       
#include 
       
       
        
        
#include 
        
        
         
         
#include 
         
         
           #include 
          
            #include 
           
             #include 
            
              #include 
             
               #include 
              
                #include "func.h" int main(int argc,char *argv[]) { if(argc!=3) { printf("error args\n"); return -1; } int fdr,fdw; fdr=open(argv[1],O_RDONLY);//打开管道1的读端 if(-1==fdr) { perror("open"); return -1; } fdw=open(argv[2],O_WRONLY);//打开管道2的写端 if(-1==fdw) { perror("open1"); return -1; } printf("open pipe success\n"); char buf[20]={0}; fd_set rdset; int ret; while(1) { FD_ZERO(&rdset);//清空集合 FD_SET(0,&rdset); FD_SET(fdr,&rdset);//把监控的描述符放到集合当中去 ret=select(fdr+1,&rdset,NULL,NULL,NULL); if(ret >0) { if(FD_ISSET(fdr,&rdset))//如果fdr可读 { memset(buf,0,sizeof(buf)); if(read(fdr,buf,sizeof(buf)-1)>0) { puts(buf); }else{ break; } } if(FD_ISSET(0,&rdset))//如果标准输入可读 { memset(buf,0,sizeof(buf)); if(read(STDIN_FILENO,buf,sizeof(buf))>0) { write(fdw,buf,strlen(buf)-1); }else{ break; } } } } close(fdr); return 0; }#include "func.h" int main(int argc,char *argv[]) { if(argc!=3) { printf("error args\n"); return -1; } int fdw,fdr; fdw=open(argv[1],O_WRONLY);//打开1号管道的写端 if(-1==fdw) { perror("open"); return -1; } fdr=open(argv[2],O_RDONLY);//打开2号管道的读端 if(-1==fdr) { perror("open1"); return -1; } printf("process 2 open pipe success\n"); char buf[20]; int ret; fd_set rdset; while(1) { FD_ZERO(&rdset); FD_SET(0,&rdset); FD_SET(fdr,&rdset); ret=select(fdr+1,&rdset,NULL,NULL,NULL); if(ret>0) { if(FD_ISSET(STDIN_FILENO,&rdset)) { memset(buf,0,sizeof(buf)); if(read(STDIN_FILENO,buf,sizeof(buf))>0) { write(fdw,buf,strlen(buf)-1);//写到对端 }else{ break; } } if(FD_ISSET(fdr,&rdset)) { memset(buf,0,sizeof(buf)); if(read(fdr,buf,sizeof(buf)-1)>0) { puts(buf); }else{ break; } } } } return 0; } #include "func.h" int main() { sleep(5); char buf[20]={0}; read(0,buf,sizeof(buf)); puts(buf); return 0; } 
               
              
             
            
           
         
        
        
       
       
      
      
     
     

mmap 对大文件的操作,文件内存映射
fd 文件打开 提供读写权限
PROT_READ|PROT_WRITE
void *mmap(void *addr,size_t length,int prot,int flags,int fd,off_t offset);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值