Linux文件编程

一、Linux系统调用及用户编程接口(API)

errno(error+number)——错误代码,自动赋值

linux中的 api函数发生异常时,一般会将errno变量(需include errno.h)赋一个整数值,不同的值表示不同的含义,可以通过查看该值推测出错的原因

1、系统调用

        操作系统提供给用户的一组“特殊”接口,用户程序可以通过这组“特殊”接口来获得操作系统内核提供的的服务

        系统调用并不是直接与程序员进行交互的,它仅仅是一个通过软中断机制向内核提交请求,以获取内核服务的接口。在实际使用中程序员调用的通常是用户编程接口—API

        系统命令相对API更高了一层,它实际上一个可执行程序,它的内部引用了用户编程接口(API)来实现相应的功能

2、用户程序不能直接访问系统内核提供的服务的原因

        由于在Linux中,为了更好地保护内核空间,将程序的运行空间分为内核空间用户空间(也就是常称的内核态和用户态),它们分别运行在不同的级别上,在逻辑上是相互隔离的。因此,用户进程在通常情况下不允许访问内核数据,也无法使用内核函数,它们只能在用户空间操作用户数据,调用用户空间的函数。

核心(Kernel)的基础功能

二、Linux中文件及文件描述符概述

 1、Linux文件

  • Linux一点哲学

    • 一切皆为文件”;在Linux中对目录和设备的操作都等同于对文件的操作;
  • 查看Linux文件类型(无后缀和扩展名)

    • ls-l/ls-ld 或者ll [ls-l —查看文件 ls-ld —查看路径 ll ----跟ls -l 一样]
    • ll anaconda-ks.cfg                       //看第一个字符
      -rw-------. 1 root root 2460 6月   1 23:37 anaconda-ks.cfg
      [root@localhost log]# ls -ld /etc   
      drwxr-xr-x. 81 root root 4096 Jan 29 03:25 /etc
      
    • file 命令
    • [root@localhost data]# file a.txt 
      a.txt: ASCII text
      
    • stat 命令
    • [root@localhost data]# stat a.txt      //查看文件的详细属性(其中包括文件时间属性)
        File: `a.txt'
        Size: 3               Blocks: 8          IO Block: 4096   regular file
      Device: 803h/2051d      Inode: 544365      Links: 1
      Access: (0644/-rw-r--r--)  Uid: (    0/    root)   Gid: (    0/    root)
      Access: 2018-01-28 20:56:01.965885036 +0800
      Modify: 2018-01-28 20:55:27.181876154 +0800
      Change: 2018-01-28 20:55:27.181876154 +0800
      
  • Linux文件可分为:普通文件,目录文件,链接文件,设备文件

①普通文件类型
Linux中最多的一种文件类型, 包括 纯文本文件(ASCII);二进制文件(binary);数据格式的文件(data);各种压缩文件.第一个属性为 [-]
②目录文件
就是目录, 能用 # cd 命令进入的。第一个属性为 [d],例如 [drwxrwxrwx]
③块设备文件
块设备文件 : 就是存储数据以供系统存取的接口设备,简单而言就是硬盘。例如一号硬盘的代码是 /dev/hda1等文件。第一个属性为 [b]
④字符设备
字符设备文件:即串行端口的接口设备,例如键盘、鼠标等等。第一个属性为 [c]
⑤套接字文件
这类文件通常用在网络数据连接。可以启动一个程序来监听客户端的要求,客户端就可以通过套接字来进行数据通信。第一个属性为 [s],最常在 /var/run目录中看到这种文件类型
⑥管道文件
FIFO也是一种特殊的文件类型,它主要的目的是,解决多个程序同时存取一个文件所造成的错误。FIFO是first-in-first-out(先进先出)的缩写。第一个属性为 [p]
⑦链接文件
类似Windows下面的快捷方式。第一个属性为 [l],例如 [lrwxrwxrwx]

⑧堆栈文件

如LIFO。第一个属性为[f].

2、文件描述符(文件id——动态分配:只要当操作这个文件时,系统才会给你分配文件描述符)

  • 文件描述符是一个非负的整数(从0开始),它是一个索引值,并指向内核中每个进程的记录表中;
  • 从3编号开始,0,1,2文件描述符有其他作用
  • 一个进程启动时,都会打开三个文件:    
    • 标准输入:       STDIN_FILENO                  0    
    • 标准输出:       STDOUT_FILENO              1    
    • 标准出错处理:STDERR_FILENO              2
  • 输入和输出
    • 头文件:<nuisted.h>
      • unistd.h是unix std的意思,是POSIX标准定义的unix类系统定义符号常量的头文件,包含了许多UNIX系统服务的函数原型,例如read函数、write函数和getpid函数
    • 实现代码
      • 因为输入有换行符,只能读入5个,所以会出错👉[root@localhost 0223] 

        改为6

         

三、无缓冲访问文件(系统调用)——无缓冲指每一个函数都只调用系统中的一个函数

1、系统调用

  • 创建

    • int creat(const char *filename,mode_t mode)
    • filename:创建的文件名
    • mode:创建模式,权限
      • 常创建模式
        S_IRUSR     可读
        S_IWUSR     可写
        S_IXUSR      可执行
        S_IXRWU     可读可写可执行
        除用以上宏来选择创建模式,也可以用数字来表示
  • 打开

    • 头文件

      • #include <sys/types.h>
      • #include <sys/stat.h>
      • #include <fcntl.h>
    • 两种调用格式          

      • int open(const char *pathname, int flags); 👉不需要创建新文件
      • int open(const char *pathname,int flags,mode_t mode); 👉创建新文件
        • pathname是要打开或创建的文件的名字
        • flags参数可用来说明此函数的多个选择项
          • 以下可选项可以同时指定0个或多个, 和必选项按位或起来作为flags参数。连接方式为管道符  |
          • O_CREAT 若此文件不存在则创建它。使用此选择项时,需同时说明第三个参数mode,用其说明该新文件的存取权限。          
          • O_NONBLOCK如果pathname指的是一个块特殊文件或一个字符特殊文件,则此选择项为此文件的本次打开操作和后续的I/O操作设置非阻塞方式。
          • O_TRUNC      打开文件长度截短为0,即清空
        • mode对于open函数而言,仅当创建新文件时才使用第三个参数
          • 即打开方式,定义在<fcntl.h>头文件
          • O_RDONLY   只读打开      
          • O_WRONLY  只写打开      
          • O_RDWR       读、写打开
          • O_APPEND    追加(只写)
    • ​​​​返回值
      • 成功返回新分配的文件描述符,
      • 出错返回-1并设置errno
    • 输出错误三方式
      • (1)errno就是error number,是由OS来维护的一个全局变量,任何OS内部函数都可以通过设置errno来告诉上层调用者究竟刚才发生了一个什么错误。

      • (2)perror()

        • 用于将上一条语句(方法)执行后的错误打印到标准输出上。一般情况下(没有使用重定向的话),就是输出到控制台上。   

          #include <stdio.h>                                                                                  void perror(const char *s);    //perror - print a system error message

      • strerror()
        • streorror=string+error,就是将errno值翻译成描述错误类型的string语句!

          #include <string.h>
          char *strerror(int errnum);   //strerror return string describing error number

           实例:

          #include<stdio.h>
           
          #include <sys/types.h>
          #include <sys/stat.h>
          #include <fcntl.h>
           
          #include <errno.h>//维护errno全局变量
          #include <string.h>//strerror函数使用
          int main(void)
          {
              int fd = -1;        // fd 就是file descriptor,文件描述符
           
                  // 第一步:打开文件
              fd = open("c.txt", O_RDWR);
              if (-1 == fd)
              {
                  perror("文件打开错误");
                  printf("error num:%d\r\n",errno);
                  printf("%s\n", strerror(errno));
                  
                  _exit(-1);
              }
              else
              {
                  printf("文件打开成功,fd = %d.\n", fd);
              }
           
              return 0;
          }


          运行结果:

  • 关闭

    • int close(int fd)
      • fd:文件描述符——对应open
    • EOF(End Of File),通常在文本的最后存在此字符表示资料结束
      • 在终端(黑框)中手动输入时,系统并不知道什么时候到达了所谓的“文件末尾”,因此需要用<Ctrl + z>组合键然后按 Enter 键的方式来告诉系统已经到了EOF,这样系统才会结束while.
  • 系统调用

      • int write(int fd, const void * buf, size_t length)    

      • 功能:把length个字节从buf指向的缓冲区中写到文件描述符fd所指向的文件中,返回值为实际写入的字节数。

      • 返回

        • 当length为0时,返回0,除此之外不会返回0
        • EOF👉不返回0
        • 0<    <length
        • =length👉输出
        • -1👉出错
    • 定位

      • int lseek(int fd, offset_t offset, int whence)
      • 功能:将文件读写指针相对whence移动offset个字节。操作成功时,返回文件指针相对于文件头的位置
      • offset
        • 可取负值,表示向前移动。
      • whence(可使用下述值)
        • SEEK_SET:相对文件开头
        • SEEK_CUR:相对文件读写指针的当前位置
        • SEEK_END:相对文件末尾
      • 例如下述调用 可将文件指针相对当前位置向前移动5个字节:
        • lseek(fd, -5, SEEK_CUR)
      • 利用lseek来计算文件长度
        • lseek函数的返回值为文件指针相对于文件头的位置 
        • lseek(fd, 0, SEEK_END)
  • 应用

四、有缓冲访问文件(库函数)

C库函数的文件操作是独立于具体的操作系统平台的,不管是在DOS、Windows、Linux还是在VxWorks中都是这些函数。

  • 创建和打开

    • FILE *fopen(const char *filename, const char *mode)
    • FILE:结构体
    • filename:打开的文件名(包含路径,缺省为当前路径)    
    • mode:打开模式
      • “r” :只读,文件必须已存在
      • “w”:只写,如果文件不存在则创建,如果文件已存在则把文件长度截断(Truncate)为0字节再重新写,也就是替换掉原来的文件内容
      • “a”:只能在文件末尾追加数据,如果文件不存在则创建
      • 👆无加号

      • 👇有加号

      • “r+”:允许读和写,文件必须已存在
      • “w+”:允讲读和写,如果文件不存在则创建,如果文件已存在则把文件长度截断为0字节再重新写
      • “a+”:允许读和追加数据,如果文件不存在则创建
    • b用于区分二进制文件和文本文件,这一点在DOS、Windows系统中是有区分的,Linux不区分二进制文件和文本文件,所以不需要"b".
    • size_t  fread(void *ptr, size_t size, size_t n, FILE* stream)
    • 功能:从stream指向的文件中读取n个字段,每字段为size字节,并将读取的数据放入ptr所指的字符数组中,返回实际已读取的字段数(n)
    • size_t fwrite (const void *ptr, size_t size, size_t n,FILE *stream)    
    • 功能:从缓冲区ptr所指的数组中把n个字段写到stream指向的文件中,每个字段长为size个字节,返回实际写入的字段数
  • 读字符

    •  int fgetc(FILE *stream)                                从指定的文件中读一个字符
    • #include<stdio.h>
      main()
      {
             FILE *fp;
             char ch;
             if((fp=fopen("c1.txt","r+"))==NULL)
             {
         	 	    printf("\nCannot open file strike any key exit!");
         	       /*
                   getchar();    //无用,让显示终端暂停可看,待输入对应字符终端显示消失
       	       */
                  exit(1);
      	 }
      
      	ch=fgetc(fp);
      	while(ch!=EOF)    //取所有
      	{
      		putchar(ch);
      		ch=fgetc(fp);
      	}
      	fclose(fp);
      
  • 写字符

    • int fputc(int c, FILE *stream)                         向指定的文件中写入一个字符
    • #include<stdio.h>
      main()
      {
      		FILE *fp;
      		char ch;
      		if((fp=fopen("string","w+"))==NULL) 
              {
      			printf("Cannot open file,strike any key exit!");
      			getch();
      			exit(1);
      		}
      		printf("input a string:\n");
      		ch=getchar();
      	
              while (ch!='\n') 
              {
      			fputc(ch,fp);
      			ch=getchar();
      		}
      	    printf("\n");
      	    fclose(fp);
          

头文件,编程接口,编程接口对应函数……类型,用法,步骤

error对应数字什么错误

处理error编号的函数


 本地存储

  • 文件操作(系统调用、C库函数)
    • C标准库提供的读写文件的fread和fwrite函数:
      FILE *fopen(char *filename, *type);
      size_t fread( void *buffer, size_t size, size_t count, FILE *stream);
      size_t fwrite( const void *buffer, size_t size, size_t count,FILE *stream);

      但是在学习UNIX / Linux环境时会发现操作系统提供的系统调用为:
      int open(const char * filename, int flag, ...)
      int read(int fildes, char * buf, off_t count);
      int write(int fildes, const char * buf, off_t count);

      C语言作为一种跨平台、可移植的高级语言,其库函数想必是对操作系统的系统调用进行了一番封装,但是仔细比较这两组函数的参数就会发现,库函数的参数相对复杂一点,而且最大的区别在于用来操作文件的部分:FILE *streamint fides...

      库函数里用一个FILE*类型的指针来操作一个打开的文件,而系统调用则使用一个整数来表示一个打开的文件

  • 数据库(数据库指令、C编程)

多任务

  • 进程
    • 创建方法:for、vfor;
    • 等待wait;
    • 退出qxit;
    • 让当前进程执行新的任务exec;
  • 进程间的通讯
    • 管道通信
      • 有名
      • 无名
    • 信号(唯一异步)
    • 共享内存;(效率高)
    • 消息队列;
  • 线程(同一进程
    • 创建(create)
    • 退出(qxit)
    • 等待(join)
    • 同步(复制锁条件变量)

网络编程

  • TCP——有链接、有协议、有先后
    • 并发
    • socket
  • UDP
    • 循环——线程节省内存空间
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值