linux系统编程 标准io

简介: linux系统编程 标准io

一、标准IO概念

标准IO在系统调用的上一层多加了一个缓冲区,也因此引入了流的概念,在UNIX/Linux下表示为FILE*(并不限于UNIX/Linux,ANSI C都有FILE的概念),FILE实际上包含了为管理流所需要的所有信息:实际I/O的文件描述符,指向流缓存的指针(标准I/O缓存,由malloc分配,又称为用户态进程空间的缓存,区别于内核所设的缓存),缓存长度,当前在缓存中的字节数,出错标志等。标准I/O对每个I/O流自动进行缓存管理,它提供了三种类型的缓存:

  • 全缓存。当填满标准I/O缓存后才执行I/O操作。磁盘上的文件通常是全缓存的。
  • 行缓存。当输入输出遇到新行符或缓存满时,才由标准I/O库执行实际I/O操作。stdin、stdout通常是行缓存的。
  • 无缓存。相当于read、write了。stderr通常是无缓存的,因为它必须尽快输出。

二、行缓存的验证案例

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{
       printf("hello world!");
       while(1)
       {       
              sleep(1);
       }
       return 0;
}    

以上程序编译后,并不能输出任何信息。原因是使用printf输出hello world后,没有换行符。printf的缓冲是属于行缓冲的,输出遇到新行符或缓冲满时,才执行标准的I/O操作。此程序由于执行到了while中的循环,一直在循环。缓冲没有满,也没遇到换行符。所以屏幕无任何输出。

当去掉while循环,程序输出后立马结束,缓存中的信息就会输出出来。

三、FILE结构体

包含于#include <stdio.h>里,以下仅是FILE结构体部分参数,具体可查看头文件。

缓存的操作如下:

缓存遇到换行符或是return/exit(_exit不行) 或者写满缓存或者调用fclose后的时候,才会输出。

数据先写进缓存,然后再输出到文件或屏幕上。

stdin:标准输入,scanf 类函数就是默认的使用此函数

stdout:标准输出,printf 函数默认使用此

stderr:标准错误

这三个就是FILE 类型结构体指针,也称为流指针

四、函数格式定义

1. fopen()函数 – 用于打开一个文件,返回一个指向该文件的文件指针

#include<stdio.h>
FILE* fopen(const char *filename, const char *mode);
  • 函数描述:fopen 打开一个指定的文件。
  • 参数说明:
filename:指定了被打开的文件的路径(相对路径或绝对路径)
 mode:指定了被打开文件的操作方式,如下:
   “r”:只读
   “w”:只写,并将文件截断为0
   “a”:只写,以追加方式从文件尾开始写
   “r+”:读写
   “w+”:读写,并将文件截断为0
   “a+”:读写,以追加方式从文件尾开始写
  • 函数返回值:
成功:指向FILE的指针
 失败: NULL

2. fdopen()函数 – 把流与一个文件句柄相接

#include<stdio.h>
FILE * fdopen(int fd,  const char * mode);
  • 函数描述:通俗的理解fdopen就是把参数fd的文件描述符转化为文件指针。
  • 参数说明:
fd: 文件描述符
 mode: 文件打开的模式。和fopen中的模式(如r-只读, w-写)相同。
  • 函数返回值:
返回文件指针。

3. freopen()函数 --预定义的标准流文件定向到由path指定的文件中

#include <stdio.h>
FILE *freopen( const char *path, const char *mode, FILE *stream ); 
  • 函数描述:
实现重定向,把预定义的标准流文件定向到由path指定的文件中。标准流文件具体是指stdin、stdout和stderr。
  其中stdin是标准输入流,默认为键盘;stdout是标准输出流,默认为屏幕;stderr是标准错误流,一般把屏幕设为默认。
  • 参数说明:
path: 文件名,用于存储输入输出的自定义文件名。
 mode: 文件打开的模式。和fopen中的模式(如r-只读, w-写)相同。
 stream: 一个文件,通常使用标准流文件。
  • 函数返回值:
成功,则返回一个path所指定文件的指针;失败,返回NULL。

4. fread()函数 – 用于从一个文件流中读取数据

#include<stdio.h>
size_t fread(void *ptr, size_t size, size_t nitems, FILE *stream);
  • 函数描述:
它与底层调用read相似,其作用是从stream读取nitems个长度为size的数据到ptr所指向的缓冲区中。
  • 参数说明:
ptr: 指定从文件流中读取的数据所存放的地方
 size: 指定所读取的每一条记录的大小,单位字节
 items: 指定本次读操作所读取的记录条数
 stream: 指定读取数据的来源—文件流
  • 函数返回值:
fread执行成功时返回实际读取记录的条数。

5. fwrite()函数 – 用于写数据到一个文件流中

#include<stdio.h>
size_t fwrite(void *ptr, size_t size, size_t nitems, FILE *stream);
  • 函数描述:
它与底层调用write相似,其作用是从stream写nitems个长度为size的数据到ptr所指向的缓冲区中。

6. fclosed函数

#include<stdio.h>
int fclose(FILE *stream);
  • 函数描述:
fclose操作将会引起所要关闭的文件流刷新缓冲区的操作,这使得该文件流上的所有读写操作都立刻执行。当程序正常终止时
    (return/exit两个函数可以,_exit不行)会对所有尚未关闭的文件流自动执行fclose操作。
  • 参数说明:
stream: 指定断开数据的来源—文件流
  • 函数返回值:
成功返回0
 失败返回EOF

7. fflush()函数

#include<stdio.h>
int fflush(FILE *stream);
  • 函数描述:
清除一个流,即清除文件缓冲区,当文件以写方式打开时,将缓冲区内容写入文件。也就是说,对于ANSI C规定的是缓冲文件系
    统,函数fflush用于将缓冲区的内容输出到文件中去。
  • 参数说明:
stream: 指定刷新数据的来源—文件流
  • 函数返回值:
如果成功刷新,fflush返回0。指定的流没有缓冲区或者只读打开时也返回0值。
 失败返回EOF指出一个错误。

8. fgetc、getc、getchar – 从指定文件流中读取一个字节的数据

#include<stdio.h>
int fgetc(FILE *stream);
int getc(FILE *stream);
int getchar();
  • 函数描述:
函数fgetc从指定的文件流中读取一个字节的数据,并返回该字节数据的整型值,当读到文件尾或发生错误时返回EOF。getc同
    fgetc,只是它有可能被实现为宏。getchar函数相当于从标准输入读取字节时的fgetc。
  • 参数说明:
stream: 指定获取数据的来源—文件流
  • 函数返回值:
成功返回该字节数据的整型值。
 失败返回EOF指出一个错误。

9. fputc、putc、putchar – 写一个字节数据到指定的文件流

#include<stdio.h>
int fputc(int c, FILE *stream);
int putc(int c, FILE *stream);
int putchar(int c);
  • 函数描述:
fputc函数将一个字节写到指定的文件流中,成功时返回返回写入的字节的整型值,失败时返回EOF。putc同fputc,只是有可能
    被实现为宏。putchar相当于向标准输出写一个字节时的fputc。
  • 参数说明:
stream: 指定写入数据的来源—文件流
  • 函数返回值:
成功返回该字节数据的整型值。
 失败返回EOF指出一个错误。

10. fgets、gets – 用于从一个文件流读取一个字符串

#include<stdio.h>
char *fgets(char *s, int n, FILE *stream);
char *gets(char *s);
  • 函数描述:
fgets函数从指定的文件流指针中读取一个字符串,直到遇到换行符或者已经读了n-1个字符或者遇到文件EOF,它会在所读取的
    数据结尾加上一个\0字符,然后放到s指定的位置。
  • 参数说明:
stream: 指定读取数据的来源—文件流
 s: 指定存放所读取的数据的位置
 n: 指定读取数据的最大长度(包括结尾的\0字符)
  • 函数返回值:
成功返回返回指向s的指针
 失败返回NULL
目录
相关文章
|
6月前
|
Ubuntu Linux Anolis
Linux系统禁用swap
本文介绍了在新版本Linux系统(如Ubuntu 20.04+、CentOS Stream、openEuler等)中禁用swap的两种方法。传统通过注释/etc/fstab中swap行的方式已失效,现需使用systemd管理swap.target服务或在/etc/fstab中添加noauto参数实现禁用。方法1通过屏蔽swap.target适用于新版系统,方法2通过修改fstab挂载选项更通用,兼容所有系统。
519 3
Linux系统禁用swap
|
6月前
|
Linux
Linux系统修改网卡名为eth0、eth1
在Linux系统中,可通过修改GRUB配置和创建Udev规则或使用systemd链接文件,将网卡名改为`eth0`、`eth1`等传统命名方式,适用于多种发行版并支持多网卡配置。
1035 3
|
Ubuntu Linux 网络安全
Linux系统初始化脚本
一款支持Rocky、CentOS、Ubuntu、Debian、openEuler等主流Linux发行版的系统初始化Shell脚本,涵盖网络配置、主机名设置、镜像源更换、安全加固等多项功能,适配单/双网卡环境,支持UEFI引导,提供多版本下载与持续更新。
621 3
Linux系统初始化脚本
|
7月前
|
运维 Linux 开发者
Linux系统中使用Python的ping3库进行网络连通性测试
以上步骤展示了如何利用 Python 的 `ping3` 库来检测网络连通性,并且提供了基本错误处理方法以确保程序能够优雅地处理各种意外情形。通过简洁明快、易读易懂、实操性强等特点使得该方法非常适合开发者或系统管理员快速集成至自动化工具链之内进行日常运维任务之需求满足。
455 18
|
6月前
|
安全 Linux Shell
Linux系统提权方式全面总结:从基础到高级攻防技术
本文全面总结Linux系统提权技术,涵盖权限体系、配置错误、漏洞利用、密码攻击等方法,帮助安全研究人员掌握攻防技术,提升系统防护能力。
593 1
|
6月前
|
监控 安全 Linux
Linux系统提权之计划任务(Cron Jobs)提权
在Linux系统中,计划任务(Cron Jobs)常用于定时执行脚本或命令。若配置不当,攻击者可利用其提权至root权限。常见漏洞包括可写的Cron脚本、目录、通配符注入及PATH变量劫持。攻击者通过修改脚本、创建恶意任务或注入命令实现提权。系统管理员应遵循最小权限原则、使用绝对路径、避免通配符、设置安全PATH并定期审计,以防范此类攻击。
1190 1
|
7月前
|
缓存 监控 Linux
Linux系统清理缓存(buff/cache)的有效方法。
总结而言,在大多数情形下你不必担心Linux中buffer与cache占用过多内存在影响到其他程序运行;因为当程序请求更多内存在没有足够可用资源时,Linux会自行调整其占有量。只有当你明确知道当前环境与需求并希望立即回收这部分资源给即将运行重负载任务之前才考虑上述方法去主动干预。
1988 10
|
7月前
|
安全 Linux 数据安全/隐私保护
为Linux系统的普通账户授予sudo访问权限的过程
完成上述步骤后,你提升的用户就能够使用 `sudo`命令来执行管理员级别的操作,而无需切换到root用户。这是一种更加安全和便捷的权限管理方式,因为它能够留下完整的权限使用记录,并以最小权限的方式工作。需要注意的是,随意授予sudo权限可能会使系统暴露在风险之中,尤其是在用户不了解其所执行命令可能带来的后果的情况下。所以在配置sudo权限时,必须谨慎行事。
1144 0
|
7月前
|
Ubuntu Linux 开发者
国产 Linux 发行版再添新成员,CutefishOS 系统简单体验
当然,系统生态构建过程并不简单,不过为了帮助国产操作系统优化生态圈,部分企业也开始用国产操作系统替代 Windows,我们相信肯定会有越来越多的精品软件登录 Linux 平台。
538 0
|
7月前
|
Ubuntu 安全 Linux
Linux系统入门指南:从零开始学习Linux
Shell脚本是一种强大的自动化工具,可以帮助您简化重复的任务或创建复杂的脚本程序。了解Shell脚本的基本语法和常用命令,以及编写和运行Shell脚本的步骤,将使您更高效地处理日常任务。
673 0