zoukankan      html  css  js  c++  java
  • 系统文件操作开发

    1、系统文件读写

    任务描述:

    编写程序,读取linux系统文件"/etc/passwd"内容,并输出到屏幕上.同时在程序目录新建文件passwd,将"/etc/passwd"系统文件内容复制到新建的passwd中

    main.c:

    #include<stdio.h>
    #include<unistd.h>
    #include<stdlib.h>
    #include<sys/types.h>
    #include<sys/stat.h>
    #include<fcntl.h>
    #define N 1000
    
    int main(void)
    {
        int fp1,fp2,num;
        char *file1,*file2;
        char buf[N];
        file1="/etc/passwd";
        file2="passwd";
        if(( fp1=open(file1,O_RDONLY))==-1){            
            printf("can't open %s
    ",file1);
            return 1;
        }
        if((fp2=open(file2,O_CREAT|O_WRONLY))==-1){
            printf("can't create %s
    ",file2);
            return -1;
        }
        while((num = read(fp1,buf,N))>0){
            printf("%s
    ",buf);
            if(write(fp2,buf,num) == -1 ){
                printf("can't write to %s
    ",file2);
                return -1;
            }
        }   
    
        close(fp1);close(fp2);
        return 0; 
    }

    2、文件内容统计操作

    任务描述:

    • 给定系统文件filesystem.manifest(dpkg-query -W --showformat='${Package} ${Version} '>filesystem.manifest)
    • 目前文件每一行格式为"软件包名 版本号",要求输出每一行的格式为"软件包名"(去除版本号相关信息)到文件filesystem.manifest.name
    • 在第一步基础上,进一步去除换行符号,使整个文件的输出为一行(不同包名用空格分割),格式为"软件包1 软件包2 软件包3...",输出到文件filesystem.manifest.name.oneline
    • 目前每一行格式为"软件包名 版本号",找到文件中软件包名有"ubuntu"字样的软件包,并直接输出其个数(不能人工查找,需直接输出其个数)

    相关知识:

    ①cut 命令可以从一个文本文件或者文本流中提取文本列。
      命令用法:
        cut -b list [-n] [file ...]
        cut -c list [file ...]
        cut -f list [-d delim][-s][file ...]
      上面的-b、-c、-f 分别表示字节、字符、字段(即 byte、character、field);
      list 表示-b、-c、-f 操作范围,-n 常常表示具体数字;
      file 表示的自然是要操作的文本文件的名称;
      delim(英文全写:delimiter)表示分隔符,默认情况下为 TAB;
      -s 表示不包括那些不含分隔符的行(这样有利于去掉注释和标题)
      上面三种方式中,表示从指定的范围中提取字节(-b)、或字符(-c)、或字段(-f)。

    xargs 是一条 Unix 和类 Unix 操作系统的常用命令。它的作用是将参数列表转换成小块分段传递给其他命令,以避免参数列表过长的问题。

    例如,下面的命令:
    rm `find /path -type f`如果 path 目录下文件过多就会因为“参数列表过长”而报错无法执行。但改用 xargs 以后,问题即获解决。
    find /path -type f -print0 | xargs -0 rm
    本例中 xargs 将 find 产生的长串文件列表拆散成多个子串,然后对每个子串调用 rm。这样要比如下使用 find 命令效率高的多。
    find /path -type f -exec rm '{}' ;
    上面这条命令会对每个文件调用"rm"命令。当然使用新版的"find"也可以得到和"xargs"
    命令同样的效果:
    find /path -type f -exec rm '{}' +
    xargs 的作用一般等同于大多数 Unix shell 中的反引号,但更加灵活易用,并可以正确处理输入中有空格等特殊字符的情况。对于经常产生大量输出的命令如 find、locate 和 grep 来
    说非常有用。

    #!/bin/bash
    
    dpkg-query -W --showformat='${Package} ${Version}
    '>filesystem.manifest
    cat filesystem.manifest|cut -d ' ' -f 1 >filesystem.manifest.name
    cat filesystem.manifest.name|xargs >filesystem.manifest.name.oneline
    cat filesystem.manifest|grep "ubuntu"|wc -l
    #-d ' '表示以空格为字符 -f 1表示输出第一列
    #xargs表示将参数列表转换成小块分段传递给其他命令,以避免参数列表过长的问题

    3、文件描述符获取

    任务描述:

    • 打印输入设备,输出设备,标准错误输出设备的文件描述符
    • 任意打开一个存在文件a,打印其文件描述符
    • 不关闭文件a,定义新的文件描述符重新打开a,打印其文件描述符
    • 关闭文件a,定义新的文件描述符重新打开a,打印文件描述符

    相关知识:

      任何打开的文件都将被分配一个唯一标识该打开文件的文件描述符,为一个大于等于 0的整数。系统启动后,默认打开的文件流有标准输入设备(STDIN)、标准输出设备(STDOUT)和标准错误输出设备(STDERR),其文件描述符分别为 0、1、2。以后打开的文件的文件描述符分配依次增加。使用 fileno()函数可以返回一个流对应的文件描述符。

    main.c:

    #include <stdio.h>
    
    int main()
    {
        FILE *fp1,*fp2,*fp3,*fp4;
        int fd;
        fd=fileno(stdin);
        printf("stdin is :%d ",fd); fd=fileno(stdout);
        printf("stdout is :%d ",fd); fd=fileno(stderr);
        printf("stderr is :%d ",fd);
      printf("open file and open again before it closed
    ");
      fp1=fopen("test.c", "r");
      fd=fileno(fp1);
        printf("main.c is %d ", fd);
      fp2=fopen("test.c","r");
      fd=fileno(fp2);
        printf("main.c is %d ",fd);
      fclose(fp1);fclose(fp2);
    
        printf("open file and open again after it closed
    ");
        fp3=fopen("test.c","r");
        fd=fileno(fp3);
          printf("main.c is %d
    ",fd);
        fclose(fp3);
        fp4=fopen("test.c","r");
        fd=fileno(fp4);
          printf("main.c is %d
    ",fd);
        return 0;
    }

    4、检测文件读写权限

    任务描述:

    • 检测文件当前读写权限,如果文件具有读权限,则打印可读信息,如果有写权限,则打印可写信息,否则返回错误信息
    • 用fcntl函数实现

    相关知识:

    fcntl 功能描述:根据文件描述词来操作文件的特性。
    文件控制函数:fcntl -- file control
    函数原型:
    #include <fcntl.h>;
    int fcntl(int fd, int cmd);
    int fcntl(int fd, int cmd, long arg);
    int fcntl(int fd, int cmd, struct flock *lock);
    描述: fcntl()针对(文件)描述符提供控制.参数 fd 是被参数 cmd 操作(如下面的描述)的描述符。针对 cmd 的值,fcntl 能够接受第三个参数 int arg。
    fcntl 函数有 5 种功能:
    1.复制一个现有的描述符(cmd=F_DUPFD).
    2.获得/设置文件描述符标记(cmd=F_GETFD 或 F_SETFD).
    3.获得/设置文件状态标记(cmd=F_GETFL 或 F_SETFL).
    4.获得/设置异步 I/O 所有权(cmd=F_GETOWN 或 F_SETOWN).5.获得/设置记录锁(cmd=F_GETLK,F_SETLK 或 F_SETLKW).

    main.c:

    #include<stdio.h>
    #include<fcntl.h>
    
    int main(void)
    { 
        FILE *fp;  
        int val,acc,a;
        if(( fp=fopen("test.c","r+")) == NULL){  
            printf("can't open the file
    ");
            return 1;
        }
        a=fileno(fp);
        val=fcntl(a,F_GETFL,0);//获得文件状态标记
        acc=val&O_ACCMODE;//把不是关于r、w、x的文件状态标记屏蔽掉
        if (acc==O_RDONLY)
            printf("read only
    ");
        if (acc==O_WRONLY)
            printf("write only
    ");
        if (acc==O_RDWR)
            printf("read write
    ");
        fclose(fp);
        return 0;
    }

    5、锁定/解锁文件

    任务描述:

    • 用fcntl函数实现锁定文件test_lock的两个区域,锁定类型均为以文件开头为锁定的起始位置,区域1锁定为供读取用,起始偏移量为10,长度为20;区域2锁定为供写入用,起始偏移量为40,长度为10.
    • 当进程锁定文件指定区域时,输出"process locking file",停顿10秒钟,关闭文件描述符,输出"process closing file"
    • 使用flock数据结构,使用fcntl函数

    相关知识:

      Linux 支持的文件锁技术主要包括劝告锁(advisory lock)和强制锁(mandatory lock)这两种。此外,Linux 中还引入了两种强制锁的变种形式:共享模式强制锁(share-mode mandatory lock)和租借锁(lease)。
      在 Linux 中,不论进程是在使用劝告锁还是强制锁,它都可以同时使用共享锁和排他锁(又称为读锁和写锁)。多个共享锁之间不会相互干扰,多个进程在同一时刻可以对同一个文件加共享锁。但是,如果一个进程对该文件加了排他锁,那么其他进程则无权再对该文件加共享锁或者排他锁,直到该排他锁被释放。所以,对于同一个文件来说,它可以同时拥有很多读者,但是在某一特定时刻,它只能拥有一个写者

      flock 函数用于实现对文件的锁定和解锁操作。此函数只能锁定整个文件,不能锁定某个区域。要锁定某个区域,则需要使用 fcntl()函数。

      int fcntl(int fd, int cmd, struct flock *lock);参数lock指针为flock 结构指针,定义如下:

      struct flock{
        short int l_type;
        short int l_whence;
        off_t l_start;
        off_t l_len;
        pid_t l_pid;
      };
      l_type 有三种状态:
        F_RDLCK 建立一个供读取用的锁定
        F_WRLCK 建立一个供写入用的锁定
        F_UNLCK 删除之前建立的锁定
      l_whence 也有三种方式:
        SEEK_SET 以文件开头为锁定的起始位置。
        SEEK_CUR 以目前文件读写位置为锁定的起始位置
        SEEK_END 以文件结尾为锁定的起始位置。
      l_start 表示相对l_whence位置的偏移量,两者一起确定锁定区域的开始位置。
      l_len表示锁定区域的长度,若果为0表示从起点(由l_whence和 l_start决定的开始位置)开始直到最大可能偏移量为止。即不管在后面增加多少数据都在锁的范围内。

      main.c:

    #include<stdio.h>
    #include<fcntl.h>
    
    int main(void)
    {
        int re,fd;
        fd=open("test_lock",O_RDWR|O_CREAT,0644);
        struct flock z1;
        z1.l_type=F_RDLCK;//建立一个供读取用的锁定
        z1.l_whence=SEEK_SET;//以文件开头为锁定的起始位置
        z1.l_start=10;
        z1.l_len=20;
        printf("Process %d locking file
    ",getpid());
        if((re=fcntl(fd,F_SETLK,&z1))==-1){
            printf("failed to lock z1");
        }
        struct flock z2;
        z2.l_type=F_WRLCK;//建立一个供写入用的锁定
        z2.l_whence=SEEK_SET;//以文件开头为锁定的起始位置
        z2.l_start=40;
        z2.l_len=10;
        if((re=fcntl(fd,F_SETLK,&z2))==-1){
            printf("failed to lock z2");
        }
        sleep( 10);
        printf("Process %d closing file
    ",getpid());
        close(fd);
        return 0;
    }

    6、使用 chmod()函数修改文件权限

    任务描述:

    • 首先使用touch命令新建3个临时文件:test1,test2,test3
    • 查看最原始文件权限情况(是否为拥有者可读写,所有其他人可读)
    • 设置test1为拥有者可读写,同组用户可读写,其他人可读;test2为拥有者可读写,同组用户可读写可执行,其他人可读;test3为拥有者可读写,同组用户可写不可读、其他用户可写不可读
    • 采用stat数据结,chmod函数
    • 输出修改权限前和修改权限后的文件属性

    相关知识:

    文件权限知识:

      Linux 系统中的每个文件和目录都有访问许可权限,用它来确定谁可以通过何种方式对文件和目录进行访问和操作。
      文件或目录的访问权限分为只读,只写和可执行三种。以文件为例,只读权限表示只允许读其内容,而禁止对其做任何的更改操作。可执行权限表示允许将该文件作为一个程序执行。文件被创建时,文件所有者自动拥有对该文件的读、写和可执行权限,以便于对文件的阅读和修改。用户也可根据需要把访问权限设置为需要的任何组合。有三种不同类型的用户可对文件或目录进行访问:文件所有者,同组用户、其他用户。
      所有者一般是文件的创建者。所有者可以允许同组用户有权访问文件,还可以将文件的访问权限赋予系统中的其他用户。在这种情况下,系统中每一位用户都能访问该用户拥有的文件或目录。
      每一文件或目录的访问权限都有三组,每组用三位表示,分别为文件属主的读、写和执行权限;与属主同组的用户的读、写和执行权限;系统中其他用户的读、写和执行权限。当用 ls -l 命令显示文件或目录的详细信息时,最左边的一列为文件的访问权限。

    main.c:

    #include<stdio.h>
    #include<sys/stat.h>
    #include<unistd.h>
    
    int main(void)
    {
        chmod("test01",S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH);
        chmod("test02",S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IXGRP|S_IROTH);
        chmod("test03",S_IRUSR|S_IWUSR|S_IWGRP|S_IWOTH);
        return 0;
    }
  • 相关阅读:
    [][]
    Spark笔记04
    Spark笔记03
    Spark笔记02
    Spark笔记01
    【熟能生巧】使用Screw快速生成数据库文档
    记一次关于jdbcTemplate.queryForList快速Debug及感悟
    【从零单排】Exception实战总结1
    【从零单排】Java性能排查实战模拟
    【从零单排】关于泛型Generic的一些思考
  • 原文地址:https://www.cnblogs.com/weijing24/p/4758443.html
Copyright © 2011-2022 走看看