系统编程(文件操作续)--C语言学习(3)

前述

今天总结一下文件操作,主要包括两部分,文件描述符的控制和my_ls的实现。

正文

1.对文件描述符进行控制操作以改变一打开文件的属性,fcntl函数原型如下

  int fcntl(int fd, int cmd);
  int fcntl(int fd, int cmd, long arg );
  int fcntl(int fd, int cmd, struct flock *flock);
  struct flock{
      short l_type;
      short l_whence;
      off_t l_start;
      off_t l_len;
      pid_t l_pid;
      }

这里主要谈涉及到文件记录锁的第三种形式。

文件记录锁

文件记录锁是当多个进程同时对文件进行操作时,通过锁限制进程对文件的操作,比如读锁(F_RDLCK)允许一块文件内容多个进程同时读,而写锁(F_WRLCK)对一块文件内容只允许一个进程写。而两种所互不兼容,即对于一个字节只能存在一种类型的锁
此时cmd参数有三种形式:F_SETLK,F_SETLKW,F_GETLK.
1.F_SETLK 设置锁,我理解为按flock指向的结构体中的信息对fd进行设置
2.F_SETLKW 与上一条相似,但当希望设置的锁由于已经存在了其他锁而被阻止时,会等待直到那锁被释放。
3.F_GETLK 检测能否设置锁,如果可以将lock的l_type设置为F_UNLCK否则返回存在冲突的一种锁的结构。
当设置锁时,流程如下(以设置写锁为例)

struct flock lock;
memset(&lock, 0, sizeof(struct flock)); //初始化结构体
lock.l_type = F_WRLCK;//设置要写的属性包括whence等
if((fcntl(fd, F_GETLK, lock)) == 0) //测试
    {
        if(lock -> l_type == F_UNLCK)
        {
            printf("lock can be set in fd\n");
        }
        else{
            if(lock -> l_type == F_RDLCK)
            printf("can't set lock ");
            else if(lock -> l_type == F_WRLCK)
            printf("can't set lock ");
        }
    }
    else {
        perror("get incompatible locks fail");
        return -1
    }
    lock.l_type = F_WRLCK;
    if((fcntl(fd, F_SETLK, lock)) == 0)
    {
        if(lock -> l_type == F_RDLCK)
            printf("set read lock\n");
        else if(lock -> l_type == F_WRLCK)
            printf("set write lock \n");
        else if(lock -> l_type == F_UNLCK)
            printf("release lock\n",);
    }
    else {
        perror("lock operation fail\n");
        return -1;
    }

    return 0;

2.my_ls的实现
感觉并不是很难,但确实有一些地方做的不好。
下面以-Rl参数作为代表说一下
我的函数调用传递的形参为文件路径,用opendir函数打开要查看的目录,返回的dir指针再传递给readdir函数用来找到ptr指针,从而得到文件名,再有文件名通过stat函数读取文件信息存放在结构体数组file中,因为结构体stat中没有成员变量保存文件名,于是我又定义了一个指针数组用来记录文件名,也方便对文件名排序。

int my_readir_rl(const char *path)
{
    DIR *dir;
    char dir_name[100][50];
    struct dirent *ptr;
    int i = 0,tem,key =0;;
    /*用路径打开目录*/
    if((dir = opendir(path)) == NULL)
    {
        perror("opendir");
        return -1;

    }
    /*将进程的当前工作目录转换为要查看的目录*/
    chdir(path);
    printf("----------------- %s------------------\n",path);
    //通过ptr获取文件名
    while((ptr = readdir(dir)) != NULL&&i < 99)
    {
        //不读取隐藏文件及目录
        if((ptr -> d_name)[0] == '.')
        continue;
        //获取文件信息存入结构体数组
        stat(ptr -> d_name, &file[i]);
        //记录文件名
        name[i] = ptr -> d_name;
        //判断当前文件是否为一个目录
        if((tem = (file[i].st_mode /512)) == 32)
        {
            //获取当前目录绝对路径
            getcwd(dir_name[key],512);
            //将子目录的目录名补全为绝对路径记录在dirname数组中
            strcat(dir_name[key],"/");
            strcat(dir_name[key], name[i]);
            key++;
        }
        i++;   
    }
    //按照文件名进行排序
    bubble_sort(i);
    //将文件权限由mode_t转换为rwx的字符串
    change_mode_t(i);
    //打印信息
    print(i);
    //将之前记录的子目录绝对路径再次调用函数读取显示信息
    for(tem =0; tem < key; tem++)
    {
        my_readir_rl(dir_name[tem]);
    }
    return 0;
}

没有采用链表的数据结构,导致并不能显示太多的文件信息。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值