zoukankan      html  css  js  c++  java
  • 文件I/O

    参考资料:W.Richard Stevens《UNIX环境高级编程》第4章、文件和目录

    《从实践中学嵌入式linux应用程序开发》(华清远见嵌入式学院)第2章、嵌入式文件和I/O编程

    资料下载:http://www.kuaipan.cn/file/id_43409466388906160.htmhttp://download.csdn.net/detail/klcf0220/7058427

    • 文件描述符

        对于linux而言,所有对设备和文件的操作都是使用文件描述符来进行的。文件描述符是一个非负的整数,它是一个索引值,并指向在内核中每个进程打开文件的记录表。当打开一个现存文件或者创建一个新文件时,内核就像进程返回一个文件描述符;当需要读写文件时,也需要把文件描述符作为参数传递给相应的函数。

        通常,一个进程启动时,都会打开3个文件:标准输入、标准输出和标准错误处理。这3个文件分别对应文件描述符为0、1和2(也就是宏替换STDIN_FILENO,STDOUT_FILENO和STDERR_FILENO,鼓励用宏替换)

    • 底层文件I/O操作

           不带缓存的文件I/O 操作,主要用到5 个函数:open、read、write、lseek和close。这里的不带缓存是指每一个函数都只调用系统中的一个函数(不理解这句话的含义)。这些函数虽然不是ANSI C的组成部分,但是是POSIX 的组成部分。                           

    使用实例:(从一个文件中读取最后10KB数据并复制到另一个文件中)

    #include<unistd.h>
    #include<stdio.h>
    #include<stdlib.h>
    #include<fcntl.h>
    #include<sys/types.h>
    #include<sys/stat.h>
    
    #define BUFFER_SIZE 1024
    #define SRC_FILE_NAME "src_file"
    #define DEST_FILE_NAME "dest_file"
    #define OFFEST 10240
    
    int main()
    {
            int src_file,dest_file;
            unsigned char buff[BUFFER_SIZE];
            int real_read_len;
    
            src_file = open(SRC_FILE_NAME,O_RDONLY);
    
            dest_file = open(DEST_FILE_NAME,O_WRONLY|O_CREAT,S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
    
            if(src_file < 0 || dest_file < 0)
            {
                    printf("open file error.\n");
                    exit(1);
            }
    
            //将源文件的读写指针移到最后10KB的起始位置
            lseek(src_file,-OFFEST,SEEK_END);
    
            //读取源文件的最后10KB数据并写到目标文件中,每次读写1KB
            while((real_read_len = read(src_file,buff,sizeof(buff))) > 0)
            {
                    write(dest_file,buff,real_read_len);
            }
            close(src_file);
            close(dest_file);
    
            return 0;
    }
    • 文件锁

    fcntl()函数

    当多个用户共同使用、操作一个文件的时候,Linux通常采用的方法是给文件上锁,来避免共享的资源产生竞争的状态。

    文件锁包括建议性锁和强制性锁。

    在linux中,实现文件上锁的函数有lockf()和fcntl(),lockf()用于对文件施加建议性锁,而fcntl()不仅可以施加建议性锁,还可以施加强制性锁。同时,fcntl()还能对文件的每一记录上锁,也就是记录锁。

    记录锁又可以分为读取锁和写入锁,其中读取锁又称为共享锁,写入锁又称为排斥锁。在文件的同一部分不能同时建立读取锁和写入锁。

    fcntl()使用实例:

    /*lock_set.c*/
    int lock_set(int fd,int type) 
    {
            struct flock old_lock,lock;
            lock.l_whence = SEEK_SET;
            lock.l_start = 0;
            lock.l_len = 0; 
            lock.l_type = type;
            lock.l_pid = -1;
    
            //判断文件是否可以上锁
            fcntl(fd,F_GETLK,&lock);
            if(lock.l_type != F_UNLCK)
            { 
                    //判断文件不能上锁的原因
                    if(lock.l_type == F_RDLCK)
                    {
                            printf("read lock already set by %d\n",lock.l_pid);
                    }
                    else if(lock.l_type == F_WRLCK)
                    {
                            printf("write lock already set by %d\n",lock.l_pid);
                    }
           //l_type可能已被F_GETLK修改过
            lock.l_type = type;
    
            //根据不同的type值进行阻塞式上锁或解锁
            if((fcntl(fd,F_SETLKW,&lock))<0)
            {
                    printf("lock failed:type = %d\n",lock.l_type);
                    return 1;
            }
    
            switch(lock.l_type)
            {
                    case F_RDLCK:
                    {
                            printf("read lock set by %d\n",getpid());
                    }
                    break;
                    case F_WRLCK:
                    {
                            printf("write lock set by %d\n",getpid());
                    }
                    break;
                    case F_UNLCK:
                    {
                            printf("release lock by %d\n",getpid());
                            return 1;
                    }
                    break;
                    default:
                    break;
            }
            return 0;
    }
    /*write_lock.c*/
    #include<unistd.h>
    #include<sys/types.h>
    #include<sys/stat.h>
    #include<stdio.h>
    #include<stdlib.h>
    #include<sys/file.h>
    #include "lock_set.c"
    
    int main(void)
    {
            int fd;
            
            fd = open("hello",O_RDWR|O_CREAT,0644);
            if(fd < 0)
            {
                    printf("open file error\n");
                    exit(1);
            }
    
            //给文件上写入锁
            lock_set(fd,F_WRLCK);
            getchar();
    
            //给文件解锁
            lock_set(fd,F_UNLCK);
            getchar();
            close(fd);
            exit(0);
    }

    用多个终端运行./write_lock可以得出:写入锁为互斥锁,同一时刻只能由一个写入锁存在。

    /*read_lock.c*/
    #include<unistd.h>
    #include<sys/types.h>
    #include<sys/stat.h>
    #include<stdio.h>
    #include<stdlib.h>
    #include<sys/file.h>
    #include "lock_set.c"
    
    int main(void)
    {
            int fd;
            
            fd = open("hello",O_RDWR|O_CREAT,0644);
            if(fd < 0)
            {
                    printf("open file error\n");
                    exit(1);
            }
    
            //给文件上写入锁
            lock_set(fd,F_RDLCK);
            getchar();
    
            //给文件解锁
            lock_set(fd,F_UNLCK);
            getchar();
            close(fd);
            exit(0);
    }

    用多个终端运行./read_lock可以得出:读取锁为共享锁,同一时刻可以有多个读取锁存在。

    • I/O多路复用

    在经典的《Unix网络编程第1卷》Chapter 6中作者详细介绍了五种I/O模型,分别为:
    - blocking I/O
    - nonblocking I/O
    - I/O multiplexing (select and poll)
    - signal driven I/O (SIGIO)
    - asynchronous I/O (the POSIX aio_functions)

    关于I/O模型可以参考http://www.cnblogs.com/leealways87/archive/2012/08/24/2654946.html

    IO多路复用—select()可以参考http://www.cnblogs.com/ggjucheng/archive/2012/01/17/2324859.html

    • 标准I/O编程

    /*用标准IO库函数编写一个文件test.tx,每隔一秒向文件中写入一行数据,类似这样:
    1. 2007-7-30 15:16:42
    2. 2007-7-30 15:16:43
    该程序应该无限循环,直到强制中断该进程为止(比如按Ctrl+C中断程序),下次再开启动程序写文件时应该将系统时间追加到源文件之后,并且序号能够接续上次的序号,比如:
    3. 2007-7-30 15:19:04
    4. 2007-7-30 15:19:05
    5. 2007-7-30 15:19:06*/
    #include <time.h>
    #include <unistd.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <strings.h>
    
    int main(void)
    {
        FILE *fp_time, *fp_line;
        int n = 0;
        fp_time = fopen("test.txt", "a");
        //setvbuf(fp_time, _IONBF, NULL, 0);
        if(access("line", F_OK)) // doesnot exist
        {
            fp_line = fopen("line", "w");
        }
        else
        {
            fp_line = fopen("line", "r+");
            fread(&n, sizeof(int), 1, fp_line);
        }
        
        char s[100];
        time_t t;
        while(1)
        {
            time(&t);
            bzero(s, 100);
            snprintf(s, 100, "%d.\t", ++n);
            snprintf(s+strlen(s), 100-strlen(s), "%s", ctime(&t));
            fputs(s, fp_time);
            fflush(fp_time);
            fseek(fp_line, 0, SEEK_SET); // rewind(fp_line);
            fwrite(&n, sizeof n, 1, fp_line);
            fflush(fp_line);
            sleep(1);
        }
    }
    作者:快乐出发0220 ;Android群:151319601 ; Linux群:96394158 ;转载请注明出处 http://klcf0220.cnblogs.com/ !!!
  • 相关阅读:
    SQL server查询笔记
    thinkphp ajax无刷新上传头像
    JSTL
    EL表达式
    jBox 弹框内容交互
    网页可读不可写
    readonly与disable的区别
    vuex 的使用
    页面向上滚动
    按照数组中的对象属性进行排序
  • 原文地址:https://www.cnblogs.com/klcf0220/p/3043611.html
Copyright © 2011-2022 走看看