zoukankan      html  css  js  c++  java
  • 系统文件操作函数

    系统级文件操作

    执行程序时会自动打开三个文件:标准输入,标准输出和标准错误输出。在C标准库中分别用FILE *stdin,stdout,stderr表示。这三个文件的描述符分别是0,1和2,保存在FILE结构体中,头文件unistd.h定义了三个文件描述符。

    #define STDIN_FILENO  0
    
    
    #define STDOUT_FILENO 1
    
    
    #define STDERR_FILENO 2
    • unlink

    #include <unistd.h>;

    int unlink(const char *pathname);

    unlink()删除一个name从文件系统,假如那个name是文件的最后链接且没有进程打开它,该文件将被删除。

    unlink()  deletes  a name from the filesystem.  If that name was the last link to a file and no processes have the file open the file is deleted and the space it was using is made available  for  reuse.
    If  the  name  was  the last link to a file but any processes still have the file open the file will remain in existence until the last file descriptor referring to it is closed.
    If the name referred to a symbolic link the link is removed.
    If the name referred to a socket, fifo or device the name for it is removed but processes which have the object open may continue to use it.

    • open&close
    #include <fcntl.h>
    
    #include <unistd.h>
    
    #include <sys/types.h>
    
    #include <sys/stat.h>
    
    int open(const char *pathname, int flags);
    
    int open(const char *pathname, int flags, mode_t mode);
    
    int close(int fd);

    pathname确省为当前路径下面。

    flags:一个值或几个值的组合。

    O_RDONLY:以只读的方式打开文件.

    O_WRONLY:以只写的方式打开文件.

    O_RDWR:以读写的方式打开文件.

    O_APPEND:以追加的方式打开文件.

    O_CREAT:假如文件不存在,创建一个文件。文件存在,不截短文件,要截短文件需指定O_TRUNC。

    O_EXCL:如果使用了 O_CREAT 而且文件已经存在,就会发生一个错误。此外,若O_CREAT与O_EXCL同时设置,并且将要打开的文件为符号连接,则将导致打开文件失败。

    O_NOBLOCK:以非阻塞的方式打开一个文件.

    O_TRUNC:如果文件已经存在,则删除文件的内容.

    O_LARGEFILE:大文件(>2G),2^31~=2G(采用64位偏移)。若不指定,文件大小达到2G时,出错退出。

    前面三个标志只能使用任意的一个。如果使用了 O_CREATE 标志,那么我们要使用 open 的第二种形式。还要指定 mode 标志,用来表示文件的访问权限.mode 可以是以下情况的组合.


    S_IRUSR 用户可以读 S_IWUSR 用户可以写 S_IXUSR 用户可以执行 S_IRWXU 用户可以读写执行


    S_IRGRP 组可以读 S_IWGRP 组可以写 S_IXGRP 组可以执行 S_IRWXG 组可以读写执行


    S_IROTH 其他人可以读 S_IWOTH 其他人可以写 S_IXOTH 其他人可以执行 S_IRWXO 其他人可以读写执行


    S_ISUID 设置用户执行 ID S_ISGID 设置组的执行 ID (s)


    我们也可以用数字(八进制0)来代表各个位的标志.Linux 总共用 5 个数字来表示文件的各种权限. 00000.第一位表示设置用户 ID.第二位表示设置组 ID,第三位表示用户自己的权限位,第四位表示组的权限,最后一位表示其他人的权限.

    每个数字可以取 1(执行权限),2(写权限),4(读权限),0(什么也没有)或者是这几个值的和。

    比如我们要创建一个用户读写执行,组没有权限,其他人读执行的文件.设置用户 ID 位那么 我们可以使用的模式是--1(设置用户 ID)0(组没有设置)7(1+2+4)0(没有权限,使用缺省) 5(1+4)即 10705:

    open("temp",O_CREAT,10705);

    同时注意:文件的最终权限,需要与umask相与。

    The letters rwxXst select file mode bits for the affected users: read (r), write  (w),  execute  (or search  for  directories) (x),

    execute/search only if the file is a directory or already has execute permission for some user (X),

    set user or group ID on execution (s),  restricted  deletion  flag  or sticky bit (t).

    注:文件即使不关闭,程序执行完后,也会回收系统资源,称为隐式回收系统资源。

    • read&write

    #include <unistd.h>;

    ssize_t read(int fd, void *buffer,size_t count);
    ssize_t write(int fd, const void *buffer,size_t count);
    
    

    返回读写的字节数。

    注:read读普通文件,读到文件尾时返回0。 write写多个字节时,要么出错,要么返回多个字节,不会返回0。两函数都可能由于信号中断而读取到少量数据。

    读写常规文件,read/write都不会阻塞;设备文件时才阻塞。

    • 示例,复制文件
    #include <stdio.h>
    
    #include <stdlib.h>
    
    #include <fcntl.h>
    
    #include <errno.h>
    
    #define BUF_SIZE  1024
    
    int main(int argc, char **argv) {
    
    int ret;
    
    int infd, outfd;
    
    int bytes_read, bytes_write, bytes_left;
    
    char buf[BUF_SIZE];
    
    char *ptr;
    
    if(argc != 3){
    
        printf("Usage: %s fromfile tofile
    ", argv[0]);
    
        exit(1);
    
    }
    
    outfd = open(argv[1], O_RDONLY);
    
    if(outfd < 0){
    
        perror("open error");
    
        exit(1);
    
    }
    
    infd = open(argv[2], O_CREAT|O_RDWR , S_IRUSR | S_IWUSR);   
    
    if(infd < 0){
    
        perror("open error");
    
        exit(1);
    
    }
    
    // read return 0, then file has finished.
    
    while(bytes_read = read(outfd, buf, BUF_SIZE)){
    
        if(bytes_read == -1){
    
            if(errno == EINTR){ // return 0 because of SIGINT, read again   
    
                continue;
    
            } else {
    
                perror("read error");
    
                exit(1);
    
            }
    
        } else if(bytes_read > 0){
    
            ptr = buf;
    
            while(bytes_write = write(infd, ptr, bytes_read)){
    
                if(bytes_write == -1){ 
    
                    if(errno == EINTR){
    
                        continue;
    
                    } else {
    
                        perror("write error");
    
                        exit(1);
    
                    }
    
                } else if(bytes_write < bytes_read){
    
                    bytes_read -= bytes_write;  
    
                    ptr += bytes_write;
    
                    continue;
    
                } else if(bytes_write == bytes_read){
    
                    break;
    
                } //for regular file, can't return 0;
    
            }           
    
        }
    
    }
    
    printf("file copy over.
    ");
    
    close(outfd);
    
    close(infd);
    
    return 0;
    
    }
    • fcntl
    #include <unistd.h>
    #include <fcntl.h>
    int fcntl(int fd, int cmd, ...);
    
    

    F_SETFL改写文件打开方式。

    F_GETFL获取文件打开方式。

    F_SETFL需第三参数,参数为文件打开标志,成功0,失败-1。

    F_GETFL不需要第三参数,成功:文件打开标志,失败-1。

        flags = fcntl(fd, F_GETFL);
        flags |= O_NONBLOCK;
        fcntl(fd, F_SETFL, flags);
    
    
    • lseek
    #include <sys/type.h>
    off_t lseek(int fd, off_t offset, int whence);
    
    

    设备文件是不可以设置偏移量的。如果不支持lseek,则lseek返回-1. 成功返回当前偏移量。 off_t =>int 从0计数偏移量。

    whence:SEEK_SET, SEEK_CUR, SEEK_END

    注:不可越界开头,可越界文件未。 可用于求当前偏移量,文件长度。 偏移量允许超过文件末尾,这种情况下,对该文件的下一次写操作将延长文件,中间空洞的地方读出来都是0。

    • truncate

    扩展文件长度

        #include <sys/types.h>
        int truncate(const char *path, off_t length);
        int ftruncate(int fd, off_t length);
    
    

    =>truncate a file to a specified length. 将文件改为指定长度,可清空文件(length = 0)。

    • 注意

    注:vi编译器在文件尾加“ ",当文件有内容时。

    open文件时,文件已缓冲到内存中,内核内存缓冲4K~8K(最小)。 库函数有缓冲区。 库函数读写时间<系统调用读写时间。

     

    strings示例

    打印文件中可打印字符,类似strings,超过拷贝区后有两种实现方案:拷贝检测到的打印字符复制到缓冲区;倒退文件当前偏移量。

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <string.h>
    #include <fcntl.h>
    
    #define     BUF_SIZE 128    
    
    int main(int argc, char **argv)
    {
        if(argc < 3){ 
            printf("Usage: %s filename num
    ", argv[0]);
            exit(1);
        }   
    
        int ret = 0;
        int fd = 0;
        char buf[BUF_SIZE] = {0};
        int num = 0;
        int i = 0, j = 0, cs_num = 0;
        int able_p = atoi(argv[2]); 
        int flag = 0;
        off_t buf_of = 0, tmp_of = 0, off = 0;
    
        if(able_p <= 2){ 
            able_p = 2;
        }   
        ret = access(argv[1], F_OK);
        if(ret != 0){
            printf("%s doesn't exist or have permission.
    ", argv[1]);
            exit(1);
        }
    
        fd = open(argv[1], O_RDONLY);
        if(fd < 0){
            perror("open");
            exit(1);
        }
    
        buf_of = 0;
        while((num = read(fd, buf + buf_of, sizeof(buf) - buf_of)) > 0){
            tmp_of = buf_of;
            buf_of = 0;
            for(i = tmp_of; i < num+tmp_of; i++){
                if( (buf[i]>= ' ') && (buf[i] <= '~')){
                    if(flag == 1){
                        putchar(buf[i]);
                        continue;
                    } else {
                        cs_num++;
                    }
                } else {
                    if(flag == 1){
                        putchar('
    ');
                        flag = 0;
                    }
                    cs_num = 0;
                }
    
                if(cs_num >= able_p){
                    for(j = 1; j <= cs_num; j++){
                        putchar(buf[i-cs_num + j]);
                    }
                    flag = 1;
                    cs_num = 0;
                    buf_of = 0;
    
                } else if(i == num - 1){
    //#if 0
                        off = lseek(fd, 0, SEEK_CUR);
                        if(off == (off_t)-1){
                            perror("lseek");
                            exit(1);
                        }
                        off = lseek(fd, off-cs_num, SEEK_SET);
                        if(off == (off_t)-1){
                            perror("lseek");
                            exit(1);
                        }
                        buf_of = 0;
                        cs_num = 0;
    //#endif 
    #if 0
                        for(j = 1; j <= cs_num; j++){
                            buf[j-1]=buf[i-cs_num+j];
                    //      printf("[[[0x%x]]]",(char)buf[j-1]);
                        }
                        buf_of = cs_num;
    #endif
    
                }
            }
        }
    
        close(fd);
        return 0;
    }
  • 相关阅读:
    自定义Android核心服务实践
    RootExplorer怎么样获取root权限的
    android性能测试工具之dumpsys
    gettimeofday() 获取当前时间(保存在结构体timeval中)
    Android学习之Service命令的妙用
    linux内存管理之非连续物理地址分配(vmalloc)
    Android dumpsys
    Linux下进程信息的深入分析
    Android调试工具之adbs
    如何分析Android的内存使用
  • 原文地址:https://www.cnblogs.com/embedded-linux/p/5037378.html
Copyright © 2011-2022 走看看