Linux-文件IO系统调用、文件夹操作系统调用与文件拷贝

Linux-文件IO系统调用、文件夹操作系统调用与文件拷贝

  • 前言
  • 一、文件IO系统调用
    • 1.1 open()系统调用
    • 1.2 create()系统调用
    • 1.3 close()系统调用
    • 1.4 write()系统调用
    • 1.5 read()系统调用
    • 1.6 lseek()系统调用
    • 1.7 文件IO系统调用源码展示与讲解
  • 二、文件夹操作的系统调用
    • 2.1 mkdir()
    • 2.2 rmdir()
    • 2.3 opendir()
    • 2.4 readdir()
    • 2.5 closedir()
    • 2.6 chdir()
    • 2.7 文件夹系统调用源码展示与讲解
  • 三、文件拷贝(文件IO系统调用实现)
  • 四、总结

注:本文系湛江市岭南师范学院物联网俱乐部原创部分训练计划,转载请保留声明。

前言

本次训练计划是Linux操作系统下的文件IO系统调用与文件拷贝,如有时间希望大家也能抽时间去玩一下Windows的文件系统调用,对比两者学习,本人因为秋招时间将至,时间仓促,暂时抽不出时间写Windows的文件系统调用方面的博客,后期会有更新!

一、文件IO系统调用

1.1 open()系统调用

int open(const char *path, int oflag, ... /*mode_t mode*/);

open()系统调用用来打开一个文件,并返回一个文件描述符(file description), 并且该文件描述符是当前进程最小、未使用的
文件描述符数值。
 参数: path: 要打开的文件、设备的路径
 oflag: 由多个选项进行“或”运算构造oflag参数 。
 必选: O_RDONLY (只读)O_WRONLY(只写)、 O_RDWR(读写) 
 可选: O_APPEND 每次写时都追加到文件的尾端。 
 O_CREAT 文件不存在则创建它,使用该选项需要第三个参数mode 
 O_TRUNC 如果文件存在,而且为只写或读写成功打开,则将其长度截取为0; 
 O_NONBLOCK 如果path是一个FIFO、块设备、字符特殊文件则此选项为文件的本次打开和后续的I/O操作
设置非阻塞模式方式。 
 O_EXEC、O_SEARCH、O_CLOEXEC、O_NOCTTY.... 
 mode: oflag带O_CREAT选项时可以用来创建文件,这时必须带该参数用来指定创建文件的权限模式,如066。 否则不
需要。使用示例代码:

int fd; 
 fd = open(“text.txt”, O_RDWR|O_CREAT|O_TRUNC, 0666); 
 fd = open(“text.txt”, O_WRONLY|O_APPEND);

1.2 create()系统调用

int creat(const char *path, mode_t mode);

此函数用来创建一个新文件并返回其fd。它等价于 open(path, O_WRONLY|O_CREAT|O_TRUNC, mode);

int fd; 
fd=creat(“text.txt”, 0644);

1.3 close()系统调用

int close(int fd);

该函数用来关闭一个打开的文件描述符,关闭一个文件时还会释放该进程加在该文件上的所有记录锁。当一个进程终止时,
内核将会自动关闭它所有打开的文件。

1.4 write()系统调用

ssize_t write(int fd, const void *buf, size_t nbytes);

write()函数用来往打开的文件描述符fd指向的文件中写入buf指向的数据,其中nbytes指定要写入的数据大小。如果返回值
<0则说明写入出错,譬如尝试往一个只读的文件中写入则会抛错,错误的原因系统会保存到errno变量中去。如果>0则为实
际写入的数据大小。

1.5 read()系统调用

ssize_t read(int fd, void *buf, size_t nbytes);

read()函数用来从打开的文件描述符对应的文件中读取数据放到buf指向的内存空间中去,最多不要超过nbytes个字节,这里
的nbytes一般是buf剩余的空间大小。如read成功,则返回实际读到的字节数(由nbytes或读到文件尾决定,其中EOF宏用
来判断是否到了文件尾),如果返回值小于0则表示出错,如尝试读一个没有权限读的文件时就会抛错。 

1.6 lseek()系统调用

off_t lseek(int fd, off_t offset, int whence);

我们在从文件里读出内容,或往文件写如内容的时候都有一个起始地址,这个起始地址就是当前文件偏移量,当我们对文件
进行读写的时候都会使文件偏移量往后偏移。这点就类似于我们打开记事本开始编辑文本时的光标,我们读或写入时从光标
所在位置开始读写,每读写一个字节都会使光标往后偏移。通过lseek()这个函数我们可以调整文件偏移量的地址。
其中 whence 可以是以下三个值:

Linux-文件IO系统调用、文件夹操作系统调用与文件拷贝_第1张图片

而offset就是相对于whence 的偏移量,譬如:
lseek(fd, 0, SEEK_SET); 将文件偏移量设置到了文件开始的第一个字节上;
lseek(fd, 0, SEEK_END); 将文件偏移量设置到文件最后一个字节上;
lseek(fd, -1, SEEK_END); 将文件偏移量设置到文件最后的倒数第一个字节上;

1.7 文件IO系统调用源码展示与讲解

#include 
#include 
#include 
#include 
#include 
#include 
#include 


#define buffsize 1024               //定义存储数据的长度大小为buffsize
#define message_str "Hello World\n" //写入创建文件的内容

int main(int argc , char *argv[])
{
  /*Linux操作系统:return 0 为正常返回,return -1 出错,很多时候会用-1、-2等数据来比较错误,用echo $?在终端会有上次运行的返回值,以此来判断程序发生错误的位置*/
  int fd = -1;                      //考虑最糟糕的情况,所以一开始赋值为-1
  int rv = -1;                      //考虑最糟糕的情况,所以一开始赋值为-1
  char buff[buffsize];              //创建buff

  fd = open("hello.txt",O_RDWR | O_CREAT | O_TRUNC , 0666); 
  if(fd < 0)
  {
    perror("创建文件失败!");
    return 0;
  }
  printf("Open file return file director:[%d]\n",fd);

  rv = write(fd,message_str,strlen(message_str));
  if(rv < 0)
  {
    printf("write %d bytes into file failure:%s\n",rv,strerror(errno));
    goto cleanup;
  }
  lseek(fd,0,SEEK_SET);
  memset(buff,0,sizeof(buff));
  rv = read(fd,buff,sizeof(buff));
  if(rv < 0)
  {
   printf("Read data from file failure: %s\n",strerror(errno));
   goto cleanup;
  }
  printf("Read %d bytes data from files: %s\n",rv,buff);
  
cleanup:
  close(fd);
  return 0 ;

}

效果图:
Linux-文件IO系统调用、文件夹操作系统调用与文件拷贝_第2张图片

二、文件夹操作的系统调用

2.1 mkdir()

int mkdir(const char *pathname, mode_t mode);//创建文件夹

2.2 rmdir()

int rmdir(const char *pathname);//删除文夹

2.3 opendir()

DIR *opendir(const char *pathname);//打开文件夹

2.4 readdir()

struct dirent * readdir(DIR *dp);//读文件夹

2.5 closedir()

int closedir(IDR *dp);//关闭文件夹

2.6 chdir()

int chdir(const char * pathname);//改变文件操作目录

2.7 文件夹系统调用源码展示与讲解

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#define TEST_DIR "dir"
int main(int argc, char **argv)
{
    int rv;
    int fd1;
    int fd2;
    DIR *dirp;
    struct dirent *direntp;
    /* 创建文件夹dir, 并设置文件夹权限为755 */
    if (mkdir(TEST_DIR, 0777) < 0)
    {
        printf("create directory '%s' failure: %s\n", TEST_DIR, strerror(errno));
        return -1;
    }
    /* 更改当前工作路径到文件夹dir下去 */
    if (chdir(TEST_DIR) < 0)
    {
        printf("Change directory to '%s' failure: %s\n", TEST_DIR, strerror(errno));
        rv = -2;
        goto cleanup;
    }
    /* 在dir文件夹下 创建普通文本文件file1.txt,并设置其权限位为644 */
    if ((fd1 = creat("file1.txt", 0777)) < 0)
    {
        printf("Create file1.txt failure: %s\n", strerror(errno));
        rv = -3;
        goto cleanup;
    }
    /* 在dir文件夹下 创建普通文本文件file2.txt,并设置其权限位为644 */
    if ((fd2 = creat("file2.txt", 0777)) < 0)
    {
        printf("Create file2.txt failure: %s\n", strerror(errno));
        rv = -4;
        goto cleanup;
    }
    /* 更改当前工作路径到父目录去 */
    if (chdir("../") < 0)
    {
        printf("Change directory to '%s' failure: %s\n", TEST_DIR, strerror(errno));
        rv = -5;
        goto cleanup;
    }
    /* 打开dir文件夹 */
    if ((dirp = opendir(TEST_DIR)) == NULL)
    {
        rv = -6;
        printf("opendir %s error: %s\n", TEST_DIR, strerror(errno));
        goto cleanup;
    }
    /* 列出dir里面的所有文件和文件夹 */
    while ((direntp = readdir(dirp)) != NULL)
    {
        printf("Find file: %s\n", direntp->d_name);
    }
    /* 关闭所有打开的文件夹 */
    closedir(dirp);
cleanup:
    if (fd1 >= 0)
    {
        close(fd1);
    }
    if (fd2 >= 0)
    {
        close(fd2);
    }
}

效果图:
Linux-文件IO系统调用、文件夹操作系统调用与文件拷贝_第3张图片

三、文件拷贝(文件IO系统调用实现)

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
char buff[1024];

int len;

int main(int argc,char const*argv[])
{
 char const *src_path = argv[1];
 char const *des_path = argv[2];
 int fd, fd2;
 fd = open(src_path,O_RDWR | O_CREAT);
 fd2 = open(des_path,O_RDWR | O_CREAT,0666);
 
 while(len=read(fd,buff,sizeof(buff)))
 {
  write(fd2,buff,len);
 } 
 return 0;
}

效果图:
Linux-文件IO系统调用、文件夹操作系统调用与文件拷贝_第4张图片

四、总结

文件IO系统调用、文件夹操作系统调用和文件拷贝,是学习Linux最为基础的一部分,但是也是很重要的一部分,后面将会使用以上三者实现树莓派与DS18B20温度传感器进行通讯并采集环境温度。

你可能感兴趣的:(linux)