底层文件操作:write,read,open,close,lseek,ioctl[奇牛学院]

Posted Respect@

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了底层文件操作:write,read,open,close,lseek,ioctl[奇牛学院]相关的知识,希望对你有一定的参考价值。

这里写目录标题

write

(1) 用法
man 2 write
(2) 返回值
成功:返回实际写入的字节数
失败:返回 -1, 错误编号设置 errno 可用( strerror(errno) ) 查看
注意:是从文件的当前指针位置写入!
文件刚打开时,文件的位置指针指向文件头

在这里插入图片描述
实例:main1.c

// main1.c
#include <errno.h>
#include <string.h>


int main(void){
        int len = 0;

        char buff[] = "hello world\\n";

        len = write(1, buff, sizeof(buff));
        if(len < 0){
            printf("write to stdout failed. reason: %s\\n", strerror(errno));
        }else {
            printf("write %d bytes.\\n", len);
        }

        len = write(2, buff, sizeof(buff));

        if(len < 0){
            printf("write to stderr failed. reason: %s\\n", strerror(errno));
        }


        return 0;
}

read

 	  (1)用法
 	       man 2 read
 	  (2)返回值
 	        >0 : 实际读取的字节数
 	        0  : 已读到文件尾
 	        -1 :出错
 	  注意:参数3表示最多能接受的字节数,而不是指一定要输入的字节数
 	  实例:main2.c
 	  运行:# ./a.out          /* 用户输入回车符时结束输入 */
 	        # ./a.out < main.c      /* 利用重定向, 使用文件main.c作为输入 */

在这里插入图片描述
在这里插入图片描述

// main2.c
#include <stdio.h>
#include <stdlib.h>

int main(void){

    char buffer[1024];
    int cnt = 0;

    cnt = read(0, buffer, sizeof(buffer));

    write(1, buffer, cnt);

    return 0;

}

open

 	  (1) 用法
 	       main 2 open
 	  (2) 返回值
 	        成功:文件描述符
 	        失败:-1
 	  (3) 打开方式
 	        O_RDONLY        只读
 	        O_WRONLY        只写
 	        O_RDWR           读写
 	          O_CREAT           如果文件不存在,则创建该文件,并使用第3个 

参数设置权限,如果文件存在 ,则只打开文件

 	        O_EXCL            如果同时使用O_CREAT而且该文件又已经存在

时,则返回错误, 用途:以防止多个进程同时创建
同一个文件

 	        O_APPEND         尾部追加方式(打开后,文件指针指向文件的末尾)
 	        O_TRUNC          若文件存在,则长度被截为0,属性不变
	example:  open("/dev/hello", O_RDONLY|O_CREAT|O_EXCL, 0777)              
 	  (4) 参数3 (设置权限)
 	        当使用O_CREAT时,使用参数3
                
 	        S_I(R/W/X)(USR/GRP/OTH)
 	        例:
 	          S_IRUSR | S_IWUSR    文件的所有者对该文件可读可写
 	          (八进制表示法)0600     文件的所有者对该文件可读可写

		
		
 	  注意:
 	        返回的文件描述符是该进程未打开的最小的文件描述符

在这里插入图片描述

// open_demo.c
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>

#define FILE_RW_LEN 1024

int main(void){
    int fd = 0;
    int count = 0;
    char buffer[FILE_RW_LEN]="I 'm Martin.";


    fd = open("./martin.txt", O_CREAT|O_RDWR|O_APPEND|O_TRUNC, S_IRWXU|S_IRGRP|S                                 _IXGRP|S_IROTH);
    //fd = open("./martin.txt", O_CREAT|O_EXCL|O_RDWR, S_IRWXU|S_IRGRP|S_IXGRP|S                                 _IROTH);

    if(fd < 0){
        printf("open file martin.txt failed. reason: %s\\n", strerror(errno));
        exit(-1);
    }



    count = write(fd, buffer, strlen(buffer));

    printf("written: %d bytes.\\n", count);

    close(fd);
}

close

      (1) 用法
            man 2 close
            
            终止指定文件描述符与对应文件之间的关联,
            并释放该文件描述符,即该文件描述符可被重新使用
            
      (2)返回值
           成功: 0
           失败: -1

在这里插入图片描述

      实例:
         使用read/write实现文件复制 
         close_demo.c 
// close_demo.c
#include <stdlib.h>
#include <stdio.h>

#define  FILE1_NAME "file1.txt"
#define  FILE2_NAME "file2.txt"

int main(void){

    int file1, file2;
    char buffer[4096];
    int len = 0;

    file1 = open(FILE1_NAME, O_RDONLY);
    if( file1 < 0){
        printf("open file %s failed\\n, reason: %s\\n", FILE1_NAME, strerror(errno));
        exit(-1);
    }

    file2 = open(FILE2_NAME, O_CREAT|O_WRONLY, S_IRUSR|S_IWUSR);

    if( file2 < 0){
        printf("open file %s failed\\n, reason: %s\\n", FILE2_NAME, strerror(errno));
        exit(-1);
    }

    while( (len=read(file1, buffer, sizeof(buffer))) > 0){
        write(file2, buffer, len);
    }

    close(file2);
    close(file1);
    return 0;
}

观察耗时
./a.out
time ./a.out

         补充:time命令
          time命令分别输出:
              real - 程序总的执行时间、
              usr - 该程序本身所消耗的时间、
              sys - 系统调用所消耗的时间 

lseek

     (1) 用法
          man 2 lseek
     (2) 返回值
          成功:返回新的文件位置与文件头之间偏移
          失败: -1

     实例:从文件偏移量100的位置拷贝100个字节到另一个文件
     lseek_demo.c
// lseek_demo.c
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#define FILE1_NAME "lseek_demo.c"
#define FILE2_NAME "lseek_demo_2.c"

#define SIZE   100

int main(void){
    int file1, file2;
    char buffer[1024];
    int ret;

    file1 = open(FILE1_NAME, O_RDONLY);
    if (file1 < 0) {
        printf("open file %s failed\\n", FILE1_NAME);
        exit(-1);
    }

    file2 = open(FILE2_NAME, O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR);
    if (file2 < 0) {
        printf("open file %s failed\\n", FILE2_NAME);
        exit(-1);
    }

    //file size
    ret = lseek(file1, 0, SEEK_END);
    printf("file size: %d\\n", ret);

    ret = lseek(file1, 100, SEEK_SET);
    printf("lseek ret: %d\\n", ret);

    ret = read(file1, buffer, SIZE);
    if(ret > 0){
        buffer[ret] = '\\0';
        printf("read[%d]: %s\\n", ret, buffer);
        write(file2, buffer, SIZE);
    }

    close(file1);
    close(file2);
    return 0;
}


ioctl

     ioctl是设备驱动程序中对设备的I/O通道进行管理的函数。所谓对I/O通道进行管理,就是对设备的一些特性进行控制,例如串口的传输波特率、马达的转速等等。是设备驱动程序中设备控制接口函数,用来控制设备.

函数名: ioctl

功 能: 控制I/O设备

用 法: int ioctl(int fd, int cmd,[int *argdx, int argcx]);

参数:fd是用户程序打开设备时使用open函数返回的文件标示符,cmd是用户程序对设备的控制命令,后面是一些补充参数,一般最多一个,这个参数的有无和cmd的意义相关。

以上是关于底层文件操作:write,read,open,close,lseek,ioctl[奇牛学院]的主要内容,如果未能解决你的问题,请参考以下文章

Unix系统编程()open,read,write和lseek的综合练习

文件操作

python学习-第七周:File操作

缓冲文件系统(fopen/fread/fwrite)和非缓冲文件系统(open/read/write)

缓冲文件系统(fopen/fread/fwrite)和非缓冲文件系统(open/read/write)

Python文件操作