利用POSIX文件函数部分实现linux中的cp功能

来源:互联网 发布:jennifer lopez知乎 编辑:程序博客网 时间:2024/06/06 03:53

利用POSIX文件函数部分实现linux中的cp功能

一、确定目标

在开始之前,我们先确定这次编程的主要目的——

  1. 实现一对一的普通文件的拷贝
  2. 类似cp程序可以在bash上直接传送参数
  3. 尽量各方面还原cp程序

二、基本知识

确定了主要目的之后,先看文件在linux系统中的有关概念

**- Linux系统中,文件的准确定义是不包含有任何其他结构的字符流。
- Linux系统提供的文件系统,是树形层次结构系统。
- Linux支持多种文件系统,最常用的文件系统是ext2系统。
- Linux系统的文件属性主要包括文件类型和文件权限两个方面**

那么我们若要实现拷贝功能,不仅要拷贝文件内容,而且要拷贝文件属性。

以下是linux系统中文件的主要类型,在此我们只实现基础的普通文件的拷贝。
这里写图片描述

以下是linux系统中文件权限的说明

*对于Linux系统中的文件来说,它的权限可以分为4种:可读取(Readable)、可写入(Writable)、可执行(eXecute)和无权限,分别用r、w、x和-表示。
Linux系统按文件所有者、文件所有者同组用户和其它用户三类规定不同的文件访问权限。
显示的作为权限的10个字符,可分为四部分:
第一位:一般表示文件类型。
第二位到第四位(第一组rwx):表示文件所有者的访问权限。
第五位到第七位(第二组rwx):表示文件所有者同组用户的访问权限。
第八位到第十位(第三组rwx):表示其他用户的访问权限。*

linux文件的其他属性如下

struct stat {        mode_t     st_mode;       //文件对应的模式,文件,目录等        ino_t      st_ino;       //inode节点号        dev_t      st_dev;        //设备号码        dev_t      st_rdev;       //特殊设备号码        nlink_t    st_nlink;      //文件的连接数        uid_t      st_uid;        //文件所有者        gid_t      st_gid;        //文件所有者对应的组        off_t      st_size;       //普通文件,对应的文件字节数        time_t     st_atime;      //文件最后被访问的时间        time_t     st_mtime;      //文件内容最后被修改的时间        time_t     st_ctime;      //文件状态改变时间        blksize_t st_blksize;    //文件内容对应的块大小        blkcnt_t   st_blocks;     //伟建内容对应的块数量      };

如果要获得文件的其他属性,可以使用stat函数或者fstat函数。

stat函数用来判断没有打开的文件,而fstat函数用来判断打开的文件。使用较多的属性是st_mode,通过此属性可以判断给定的文件是一个普通文件还是其他文件类型

不带缓存的文件I/O操作,又称系统调用I/O操作,符合POSIX标准,设计的程序能在兼容POSIX标准的系统间方便地移植

POSIX文件函数如下

这里写图片描述

这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述

那么到此我们实现cp的基本知识已经具备。

三、编写并调试程序

c语言代码如下

#include<stdio.h>#include<stdlib.h>#include<sys/types.h>#include<sys/stat.h>#include<limits.h>#include<unistd.h>#include<fcntl.h>#include<string.h>int main(int argc, char *argv[], char *env[]){  struct stat stc,stt;  int i;  char *tmp,buf[65535],src[1024],aim[1024];  int fps,tar;//文件  realpath(argv[1],src);  realpath(argv[2],aim);   stat(src,&stc);  if (S_ISDIR(stc.st_mode))//是目录  {perror("源文件是目录形式!");exit(1);}  else  {    fps=open(src,O_RDONLY);    if(fps==-1)    {perror("源文件打开失败!");exit(1);}    //read(fps,buf,stc.st_size);  }  stat(aim,&stt);  if (S_ISDIR(stt.st_mode))//第二参数是目录  {    tmp=strrchr(src,'/');//查找到最后一个/    strcat(aim,tmp);//组合获得原有文件名  }  tar=open(aim,O_CREAT|O_RDWR,stc.st_mode);  if(tar==-1)  {perror("目标文件打开(创建)失败!");exit(1);}  while((i=read(fps,buf,65535))>0)  {write(tar,buf,i);  }  close(fps);  close(tar);  return 0;}

将编写后的可执行文件放入/usr/bin下便可在bash中调用。

写在最后

经过这次的学习,可以了解到不带缓存的文件i/o操作(系统调用),那么我由这次编程联想到进程之间的管道(pipe)通信。pipe也很巧合的使用了不带缓存的文件i/o操作。那么两者间的原理是一样的吗?在之后的学习中,查阅相关的资料后我再论述。

2 0
原创粉丝点击