• 文件I/O操作(1)


    linux系统调用和用户编程接口(api)

    系统调用是指在操作系统提供给用户程序调用的一组“特殊”的接口,用户程序可以通过这组特殊的接口来获取操作系统内核提供的服务,例如用户可以通过进程控制相关的系统调用来创建进程,实现进程调度,进程管理

    为什么用户不能直接访问系统内核提供的服务?这是因为在linux中,为了更好地保护内核空间,将程序运行的空间分为内核空间和用户空间(也就是常称为的内核态和用户态)

    内核态和用户态运行在不同的级别上,在逻辑上也是相互隔离的,新词用户进程在通常情况下是不允许范围内核数据,也无法使用内核的函数,他们只能在用户空间操作用户数据,调用用户空间的函数

    但是,在有些情况下,用户空间的进程需要获得一定的系统服务,调用内核空间程序,这时操作系统就必须利用系统提供给用户的特殊接口,系统调用规定用户进程进入内核空间的具体位置,进行系统调用的时,程序从用户空间进入内核空间,处理完后在返回用户空间

    linux系统调用部分是非常精简的系统调用(只有250)他继承了unix系统调用最基本和最有用的部分,这些系统调用按照功能和逻辑大致可以分为

    进程控制,进程间通信,文件系统控制,系统控制,存储管理,网络管理,socket控制,用户管理

    用户编程的api

    前面讲到的系统调用便不是直接与程序员进行交互,它仅仅是一个软中断机制向内核提出请求,以获取内核服务的接口,在实际使用中,程序员调用的是用户编程对应的接口--api

    linux中文件及文件描述符概述

    在linux中对目录和设备的操作都等同于对文件的操作,因此大大简化了系统对不同设备的处理,linux中的文件主要分为4种,普通文件,目录文件,链接文件和设备文件,对于linux而言,所有对设备和文件的操作都是使用文件描述符来进行的

    文件描述符是一个非负整数,他是一个索引值,并指向内核中每个进程打开文件的记录表,当打开一个现存文件,或者是创建一个新的文件时,内核就像进程返回一个文件描述符,但需要写入文件时,也需要吧文件描述符作为参数传递给相应的函数

    通常一个进程启动时,都会打开三个文件,标准输入,标准输出,标准出错处理,对应文件描述符为0,1,2。

    基于文件描述符的I/0操作虽然不能移植到类linux以外的系统上去(如windows)但它往往是实现某些I/0操作的唯一途径,基于文件描述符的I/O操作时linux中对常用的操作之一

    底层文件I/O操作

    这里主要是5个函数open(),read(),write(),lseek(),和close()这些函数的特点是不带缓存,直接对文件(包括设备)进行读写操作

    open()函数用于打开或创建文件,在打开或创建文件时,可以指定文件的属性和用户的权限等各种参数。

    close()是一个用于关闭一个被打开的文件。当一个进程终止时,所有被他打开的文件都由内核自动关闭,很多程序都使用这一功能而不显示的关闭一个文件

    read()函数用于将从指定的文件描述符中读取数据放到缓存区,并返回实际读入的字节数,若返回0,则表示没有数据可读,即已经达到文件尾,读操作文件从文件的当前指针位置开始,当从终端设备文件中读取数据时,通常一次最多读取一行

    write()函数用于向打开的文件中写入数据,写操作从文件的当前指针位置开始,对磁盘文件进行写操作,若磁盘已经写满,或者超出文件的长度,则write()函数返回失败

    lseek()函数用于在指定的文件描述符中将文件的指针定位到相应的位置,它只能用在可定位(可随机访问)文件操作中,管道,套接字,和大部分字符设备文件是不可定位的,所以在这些文件的操作中无法使用lseek

    open函数的原型 int open(const char *pathname ,int flags);pathname是指文件的路径名和名称,可以是绝对路径或者是相对路径,flag 是指定了文件的打开方式

    O_RDONLY 以只读方式,要求文件存在

    O_WRONLY以只写的方式打开,要求文件存在

    O_RDWR可读可写的方式打开,要求文件存在

    O_CREAT 创建文件

    O_EXCL创建互斥

    O_APPEND 以追加的方式写入首先要有写权限

    O_TRUNC 清空原文件内容

    返回值 为文件描述符,非负整数,文件后续操作的标志

    open的另外一种原型为int open(const char *pathname,int flags,mode_t mode)前面的参数和一样,mode是指创建文件时的权限0x777 0x644 0x664等等

    打开文件失败的原因分析:1文件不存在时指定可读,2文件所在目录无操作权限 3其他原因,文件操作权限,文件是否可用

    close函数 函数原型为int close (int fd);

    fd为open返回值的文件描述符,关闭文件后,该文件描述符将不可再用,返回值表示关闭是否成功,但我们编程时不处理该返回值,打开文件必须关闭,否则会造成文件描述符的泄漏,特别是异常情况,可以关闭0,1,2;

    示例代码:

    read 函数原型为 int read(int fd, void *buf,int count);fd为文件描述符(注意此处不能是文件名),buf为存储读取的内容的内存地址(指针),一定不能是野指针或者是空指针,count是本次读取的字节数,要求count要小于等于buf的大小,如果存储字符串时,返回值为成功读取的字节数,如果读取失败,返回小于0的值,返回值为0表示读取到文件末尾

    示例代码:

    #include<stdio.h>
    #include<sys/types.h>
    #include<sys/stat.h>
    #include<fcntl.h>
    #include<unistd.h>
    
    int main(void)
    {
                  int fd1,size;
                  char buf[128];
    
                  fd1 = open("/etc/net/works",O_RDONLY);
                  if(fd1<0)
                         {
                            printf("open fail
    ");
                            exit(0);
                         }
                  while(1)
                          {
                             size = read(fd1,buf,64);
                             if(size<0)
                                    {
                                     printf("read error
    ");
                                     exit(1);
                                     }
                             if(size ==0break;
                             buf[size+1] = '';
                             printf("%s",buf);
    
                           } 
                  close(fd1);
           
                  return 0;  
    }                                                                                        

    memset用于在某段内存中填充那一个数,函数包含的头文件是#include<string.h>函数原型为

    void *memset(void *s,int c,size_t n);例如memset(buf,0,,128);

    注意 :read函数会自动对文件的操作位置进行偏移,读完几个字节,之后就偏移几个字节,自动偏移,如果到达文件末尾,不能再次偏移

    如果读取失败的原因:

    1文件的读取权限问题

    2,文件没有内容,需要注意,如果使用O_TRUNC时,文件内容已经被清楚

    3:如果该处出现段错误,这主要考虑内存指针是否为野指针或者是否越界

    write函数;函数原型为 int write(int fd, void *buf,int count);

    fd为写入的文件描述符,buf为需要写入的内容的指针,count是写入的字节数,这里的buf要小于buf的有效值,返回值为成功写入的字节数,返回值小于0表示写入失败

    write也会对文件的操作位置进行偏移,如果为追加方式时,从文件的末尾开始写入,如果写入失败,如果写入失败,这分析原因为:1)文件是否有写权限,2)文件写入多错误时,可以查看内存是否越界,3)注意使用)O_TRUNC会清空原内容

    #include<stdio.h>
    #include<sys/stat.h>
    #include<sys/types.h>
    #include<fcntl.h>
    #include<string.h>
    #include<unistd.h>
    
    int main(void)
    {
            int fd1,fd2,size,f3;
            char buf[128];
    
            fd1 = open("/etc/xinetd.d/daytime",O_RDONLY);
            if(fd1<0)
            {
                    printf("open fail
    ");
                    exit(1);
            }
    
            fd2 = open(""daytime1",O_RDWR|O_CREAT,777);
            if(fd2<0)
            {
                                                                  1,1           Top
              printf("create daytime1 fail
    ");
                    exit(1);
            } 
            
            while(1)
            {
                    memset(buf,0,127);
                    size = read(fd1,buf,127);
    
                    if(size<0)
                    {
                            printf("read fail
    ");
                            exit(1);
                    }
                    
                    if(size==0)
                            break;
    
                    buf[128]='';
                    printf("%s",buf);
    
    
                    f3 = write(fd2,buf,size);
                    if(f3<0)
                    {
                            printf("write fail
    ");
                            exit(1);
                    }
    
            }
    
            close(fd1);
            close(fd2);
    
            return 0;
    }

     版权所有,转载请注明转载地址:http://www.cnblogs.com/fengdashen/p/3300614.html

  • 相关阅读:
    数据结构基础知识(2)
    ASIHttpRequest异步请求网络崩溃解决
    [置顶] Android仿人人客户端(v5.7.1)——采用ViewGroup做父容器,实现左侧滑动菜单(三)
    Linux中ifcfgeth0配置参数说明
    什么是redis
    CentOS网络接口配置文件ifcfgeth详解
    查看Linux版本
    CentOS7 network.service loaded failed 处理技巧
    如果这都不算爱
    ACL Security In Seam, Part 1
  • 原文地址:https://www.cnblogs.com/fengdashen/p/3300614.html
Copyright © 2020-2023  润新知