zoukankan      html  css  js  c++  java
  • Android系统开发(7)——标准I/O与文件锁

    一、常用函数

    fopen:
    FILE *fopen(const char *filename, const char *mode);
    fread:
    size_t  fread(void *ptz, size_t size, size_t nitems, FILE *stream);
    fwrite:
    size_t fwrite(const void *ptz, size_t size, size_t nitems, FILE *stream);
    fclose:
    int fclose(FILE *stream);
    fflush:
    int fflush(FILE *stream);
    fseek:
    int fseek(FILE *stream, long int offset, int where);
    fgetc,getc,getchar
    int fgetc(FILE *stream);
    int fgetc(FILE *stream);
    int getchar(); //标准输入
    fputc,putc,putchar
    int fputc(int c, FILE *stream);
    int putc(int c, FILE *stream);
    fgets,gets
    char *fgets(char *s, int n, FILE *stream);
    fputs,puts
    int *fputs(char *s, FILE *stream);
    int *puts(char *s);
    在同级目录下建立一个文件file.in,用下面的代码实现文件拷贝(函数的参数可以使用man查找,或者参考libc文档)
    #include <stdio.h>
    
    int main(){
            char c;
            FILE *pin, *pout;
            //open file
            pin = fopen("file.in", "r");
            pout = fopen("file.out", "w+");
            while(c = fgetc(pin) != EOF){
                    fputc(c, pout);
            }
            fclose(pin);
            fclose(pout);
    
            return 0;
    }
    当我们很清楚我们的物理资源和不想让一些缓存来干扰我们的时候(实时性要求高的地方)就可以使用底层的I/O操作,大部分情况下使用标准I/O操作就可以到达我们的要求。

    二、文件锁定

    假如有一个文件a,如果进程A在操作(修改)的时候,进程B有可能正在读文件,这样就会出现问题(有点像线程同步问题)。文件的锁定方式有文件型的记录型的两种,对文件的操作可分为独占和并发。
    打开linux内核源码,可以看到内核中对文件锁如下定义
    struct file_lock {
    	struct file_lock *fl_next;	/* singly linked list for this inode  */
    	struct list_head fl_link;	/* doubly linked list of all locks */
    	struct list_head fl_block;	/* circular list of blocked processes */
    	fl_owner_t fl_owner;
    	unsigned char fl_flags;
    	unsigned char fl_type;
    	unsigned int fl_pid;
    	struct pid *fl_nspid;
    	wait_queue_head_t fl_wait;
    	struct file *fl_file;
    	loff_t fl_start;
    	loff_t fl_end;
    
    	struct fasync_struct *	fl_fasync; /* for lease break notifications */
    	unsigned long fl_break_time;	/* for nonblocking lease breaks */
    
    	const struct file_lock_operations *fl_ops;	/* Callbacks for filesystems */
    	const struct lock_manager_operations *fl_lmops;	/* Callbacks for lockmanagers */
    	union {
    		struct nfs_lock_info	nfs_fl;
    		struct nfs4_lock_info	nfs4_fl;
    		struct {
    			struct list_head link;	/* link in AFS vnode's pending_locks list */
    			int state;		/* state of grant or error if -ve */
    		} afs;
    	} fl_u;
    };
    在Linux中有强制锁和建议锁两种锁,强制锁由系统内核空间支持(和内核操作相关的函数都会判断),建议锁其实就是一个标识锁由用户空间支持(手动判断)。
    可以使用 man fcntl来查看
    int fcntl(int fildes, in cmd, struct flock *arg);
    需要的头文件:<unistd.h><fcntl.h>
    参数二cmd:
    F_GETLK  //得到锁
    F_SETLK  //设置锁
    F_SETLKW   //设置锁并等待返回
    参数三:
               struct flock {
                   ...
                   short l_type;    /* Type of lock: F_RDLCK(共享锁),
                                       F_WRLCK(独占锁), F_UNLCK (删除锁)*/
                   short l_whence;  /* How to interpret l_start:
                                       SEEK_SET, SEEK_CUR, SEEK_END */
                   off_t l_start;   /* Starting offset for lock (起点)*/
                   off_t l_len;     /* Number of bytes to lock(长度) */
                   pid_t l_pid;     /* PID of process blocking our lock
                                       (F_GETLK only)(拥有锁的进程ID号) */
                   ...
               };
    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/stat.h>
    #include <sys/types.h>
    #include <unistd.h>
    #include <fcntl.h>
    
    int main(){
            //open file
            int fd = open("hello", O_RDWRIO_CREAT, 0666);
            if(fd > 0){
                    //lock file
                    struct flock lock;
                    lock.l_type = F_WRLCK;
                    lock.l_whence = SEEK_SET;
                    lock.l_start = 0;
                    lock.l_len = 0;
                    lock.l_pid = getpid();
                    int rd = fcntl(fd, F_SETLK, &lock);
    
                    printf("return value of lock:%d
    ", rd);
                    while(1){
                            rd++;
                    }
            }
            return 0;
    }

    三、错误处理

    系统级调用函数失败之后会设置外部变量error的值来指明失败原因。然后可以使用perror将最新的error输出。
    #include <stdio.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    
    int main(){
            int fd = open("helloworld", O_RDONL, 0666);
            if(fd < 0){
                    perror("open error");
            }
    
            return 0;
    }

  • 相关阅读:
    Redis详解----- 缓存穿透、缓存击穿、缓存雪崩
    mysql存储时间
    MAT入门到精通
    meven依赖思考记录
    线程池原理
    vscode + wsl2
    java架构师学习路线-高级
    java架构师学习路线-初级
    (二)垃圾回收
    (一)内存区域
  • 原文地址:https://www.cnblogs.com/lanzhi/p/6468810.html
Copyright © 2011-2022 走看看