Linux下文件I/O系统调用

て烟熏妆下的殇ゞ 提交于 2020-03-02 04:30:20

 


  • 文件类型

             Linux系统中把一切都看做文件,Linux有7中类型文件:普通文件-、目录(dierectory)文件、符号(link)链接、字符 (character)设备文件、块(block)设备文件、管道(pipe)文件、套接字(socket)文件。其中文件、目录、符号链接会占用磁盘 空间来存储,而块设备、字符设备、套接字、管道是伪文件,并不占用磁盘空间。

文件类型
文件类型标识   文件类型
 
-  普通文件
d  目录文件
l  符号链接
c  字符设备
b 块设备
p  管道
s  套接字socket 
  • 文件描述符 

文件描述符(file descriptor,  fd)是Linux内核为了高效管理已被打开的文件所创建的索引,其是一个非负整数(通常是小 整数),用于指代被打开的文件,所有执行I/O操作的系统调用都通过文件描述符。程序在开始运行时,系统会自动打开三个 文件描述符,0是标准输入,1是标准输出,2是标准错误。POSIX标准要求每次打开文件时(含socket)必须使用当前进程 中最小可用的文件描述符号码,因此第一次打开的文件描述符一定是3.

文件描述符  用途  POSIX文件描述符 标准I/O文件流
0  标准输入   STDIN_FILENO   stdin
1 标准输出   STDOUT_FILENO   stdout
2  标准出错   STDERR_FILENO  stderr
  • 文件I/O操作函数

  • open()

  • 函数原型

 int open(const char *pathname, int flags);
 int open(const char *pathname, int flags, 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.... 

  • 示例代码

int    fd;  //文件描述符              
fd = open(“text.txt”, O_RDWR|O_CREAT|O_TRUNC, 0666); 
/*
*  以可读可写形式打开text.txt,如果文件不存在,则创建该文件,权限为0666 如果文件存在,将其长度截取为0; 
*/                      
                 
fd = open(“text.txt”, O_WRONLY|O_APPEND);
/*
*以只读的形式打开已经存在的文件text.txt, 并且每次写时都追加到文件的尾端。
*
*/
  • 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); //以0644形式创建text.txttext.txt
  • close()

  • 函数原型

int  close(int   fd);
  • 示例代码

close(fd); //fd为我们要关闭的文件描述符
  • lseek()

  • 函数原型

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

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

whence

位置
SEEK_SET  文件头
SEEK_CUR 当前位置
SEEK_END 文件尾
  • 示例代码

// 而offset就是相对于whence 的偏移量,譬如:

lseek(fd, 0, SEEK_SET);  //将文件偏移量设置到了文件开始的第一个字节上; 

lseek(fd, 0, SEEK_END); //将文件偏移量设置到文件最后一个字节上;

lseek(fd, -1, SEEK_END);//将文件偏移量设置到文件最后的倒数第一个字节上;
  • read()

  • 函数原型

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

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

  • 示例代码

int rv = 0;
rv = read(fd, buf, strlen(buf)); //如果成功,rv 值为read读到实际字节数;如果read失败,则rv <0;

  • write()

  • 函数原型

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

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

  • 示例代码

int rv = -1;

rv = write(fd, buf, strlen(buf)); //如果write成功,则rv的值为实际写到buf中的字节数,出错则rv的值小于 0;
  • dup()dup2()

  • 函数原型

int  dup(int  fd); 
int dup2(int fd, int fd2);

     这两个函数都可以用来复制一个新的文件描述符来指向fd对应的文件。这两个系统调用经常用在标准输入、标准输出、标准 出错重定向。
dup()返回的新文件描述符一定是当前可用文件描述符中的最小数值; dup2可以用fd2参数来指定新的文件描述符。如果fd2已经打开,则先关闭。如fd等于fd2, 则dup2返回fd2, 而不关闭它。

模式

 说明

 

R_OK

测试读许可权

W_OK

测试写许可权

X_OK

测试执行许可权

F_OK

测试文件是否存在

  • 示例代码

dup2(fd, STDIN_FILENO);   //标准输入重定向到 std.txt 文件中去   

dup2(fd, STDOUT_FILENO);  //标准输出重定向到 std.txt 文件中去  
  
dup2(fd, STDERR_FILENO);  //标准出错重定向到 std.txt 文件中去
 
  • access()系统调用

  • 函数原型

int access(const char *path, int mode);

  access()可以用来测试文件是否存在或测试其权限位,其中第一个参数path是相应的文件路径名,第二个参数是要测试的模 式。其中mode说明如下:

  • 示例代码

#include <stdio.h>
#include <unistd.h>
#define TEST_FILE "access.c" 
int main(void)
{   
    if( access(TEST_FILE, F_OK)!=0 )    
    {      
          printf("File %s not exist!\n", TEST_FILE);      
          return 0;    
    }
    printf("File %s exist!\n", TEST_FILE);

    if(access(TEST_FILE, R_OK)==0)        
        printf("READ OK\n");

    if(access(TEST_FILE, W_OK)==0)          
        printf("WRITE OK\n");

    if(access(TEST_FILE, X_OK)==0)        
        printf("EXEC OK\n");

    return 0;
}

 

  • 文件i/o基本的使用示例

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#define   S_BUFFER       1024
#define	  MSG_STR        "Hello word"

int main (int argc, char **argv)
{
    int       fd;
    int       rv = -1;
    char      buf[S_BUFFER];
    fd = open("test.txt", O_RDWR|O_CREAT|O_APPEND, 0666);  // open()的使用
    if(fd < 0)
    {
        printf("Open/create: %s failure : %s\a\n","text.txt",strerror(errno));
        return 0;
    }
    printf("open/create file test.txt descriptor[%d]\n", fd);
    memset(buf,0,sizeof(buf));     //清空buf

    if( rv = write(fd, MSG_STR, strlen(MSG_STR))<0)  //write 数据到buf
    {

        printf("Open/create: %s failure : %s\a\n","text.txt",strerror(errno));
        goto cleanup;  //goto语句使用,用来出错处理
    }

    lseek(fd,0,SEEK_SET);  //设置文件偏移量

    if(( rv = read(fd, buf,sizeof(buf) ))<0 )  //read数据到buf
    {
 
        printf("Open/create: %s failure : %s\a\n","text.txt",strerror(errno));
        goto cleanup;
    }
    printf("read %d bytes from test.txt: %s\n",rv,buf);


cleanup:
    close(fd);
            

    return 0;
} 



 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!