重头开始嵌入式第十八天(Linux系统编程 标准IO)

Linux系统编程内容

 

Linux 系统编程涵盖了众多方面的知识和技术:
 
1. 文件 I/O 操作:包括打开、读取、写入、关闭文件,以及处理文件的权限、属性等。
2. 进程管理:创建新进程、进程的终止、等待进程结束、进程的执行状态控制等。
3. 信号处理:接收和处理系统发送的各种信号,以响应特定的事件。
4. 线程编程:创建、同步和管理线程,实现多线程并发执行。
5. 进程间通信(IPC):如管道、消息队列、共享内存、信号量等方式,实现不同进程之间的数据交换和协调工作。
6. 套接字编程:用于网络通信,实现客户端与服务器之间的数据传输。
7. 系统调用和库函数:熟练使用 Linux 提供的系统调用和相关的库函数来完成各种任务。
8. 内存管理:包括动态内存分配(如 malloc 和 free )以及对内存映射文件的操作。
 
这些是 Linux 系统编程的核心内容,通过学习和实践这些方面,可以开发出高效、稳定的 Linux 应用程序。从今天开始就正式进入系统编程内容了

 

文件IO

 

1. 标准IO的概念

标准输入输出(I/O)是与计算机程序交互的基本方式。ISO C标准提供了一套标准的输入输出库,使程序能够方便地处理输入输出操作。

- **输入(I)**:在C语言中,通常情况下,标准输入设备是键盘。程序默认从键盘读取数据。Linux中,标准输入对应的设备为`/dev/input`。
  
- **输出(O)**:标准输出设备通常是显示器,程序默认将结果输出到屏幕。

在Linux操作系统中,I/O操作都是围绕文件进行的。标准I/O库是对文件I/O的封装,使得任何支持C语言的系统都能通用地处理文件存储。

标准I/O操作通常是针对普通文件的,它采用了缓冲机制。缓冲区位于文件I/O与用户程序之间,这种设计可以有效减少系统调用的次数,从而提高效率并节省IO调度资源。

2. 文件的概念及作用

在Linux及Unix-like操作系统中,一切皆文件。文件不仅存储数据,还可以存储指令和配置。在这种模型中,文件可以分为几种类型:

- **普通文件**:用于存储数据,比如文本文件和二进制文件。
- **目录文件**:用于组织文件系统中的其他文件。
- **设备文件**:用于与硬件设备交互,比如硬盘、打印机等。
  
文件在操作系统中扮演了重要的角色:

- **数据持久化**:文件可存储重要数据和状态,使其在程序结束后不丢失。
- **信息共享**:不同程序可以通过文件共享数据。
- **配置管理**:许多程序使用配置文件来设定选项和参数,便于用户调整行为。

通过标准I/O操作,程序可以方便地读写各种类型的文件,实现更复杂的数据处理和交互功能。

在Linux中,文件的类型有以下7种:

  1. "d" - 目录文件(directory file)
  2. "-" - 普通文件(regular file)
  3. "l" - 符号链接文件(symbolic link file)
  4. "p" - 命名管道文件(named pipe file)
  5. "s" - 套接字文件(socket file)
  6. "c" - 字符设备文件(character device file)
  7. "b" - 块设备文件(block device file)

其中,d表示目录文件,-表示普通文件,l表示符号链接文件,p表示命名管道文件,s表示套接字文件,c表示字符设备文件,b表示块设备文件。

关于IO的分类,有以下几种:

  1. 标准IO(Standard IO):ANSI C设计的一组用文件IO封装的操作库函数,通过头文件stdio.h进行操作。
  2. 文件IO(File IO):底层软件的系统调用,用于对文件进行读写操作。
  3. ASCII码数据流:以ASCII码作为数据流的文本流。
  4. 二进制数据流:以二进制数据作为数据流的二进制流。

文件流是通过FILE结构定义的对象,用FILE指针来表示。文件流可以理解为数据从文件中流入和流出所体现出来的字节流,它由文件的头部和尾部组成。

在Linux中,可以使用man命令来查看有关命令、系统调用函数和标准库函数的帮助信息。man命令后面跟着的数字表示查看的是哪个部分的帮助信息,例如man 1 xxx表示查看命令xxx的帮助信息,man 2 xxx表示查看系统调用函数xxx的帮助信息,man 3 xxx表示查看标准库函数xxx的帮助信息。

对于文件IO相关的标准库函数,可以使用stdio.h头文件来使用,该头文件位于/usr/include/stdio.h。标准库函数分为系统库函数和用户自定义函数,系统库函数的默认路径是/usr/include/,而用户自定义函数的默认路径是当前路径。例如,可以使用printf、scanf、getc等函数来进行标准输入输出的操作。

文件内容可以分为文本文件和二进制文件。文本文件是以ASCII码数据流的形式存储的文件,而二进制文件是以二进制数据流的形式存储的文件。

3.文件流(File stream)

 

文件流(File stream)是指将文件的读写操作视为数据流的形式。在编程中,文件流可以用于读取和写入文件中的数据。

文件流有两种类型:输入流和输出流。输入流用于从文件中读取数据,输出流用于向文件中写入数据。

使用文件流进行文件读写的过程如下:

1. 打开文件流:使用相应的编程语言提供的函数或方法,打开要读取或写入的文件,并创建文件流对象。

2. 读取或写入数据:使用文件流对象的读取或写入方法,进行数据的读取或写入操作。读取操作会从文件中读取一定数量的数据,写入操作会将指定的数据写入文件。

3. 关闭文件流:使用相应的编程语言提供的函数或方法,关闭文件流并释放相关资源。

文件流的优点是可以按照流的方式读取或写入文件,适合处理大文件或需要逐行读取的场景。文件流也可以按字节进行读写,适合处理二进制文件。

文件流在编程中广泛应用于文件读写、日志记录、数据备份等场景。常用的编程语言如C、C++、Java、Python等都提供了对文件流的支持。

4.相关函数

fopen

在 C 语言中, fopen  函数用于打开文件。

其函数原型为:

FILE *fopen(const char *filename, const char *mode);

 

-  filename :要打开的文件名(包括路径)。

-  mode :指定打开文件的模式,常见的模式有:

-  "r" :以只读方式打开文件,如果文件不存在则打开失败。

-  "w" :以只写方式打开文件,如果文件不存在则创建,如果存在则清空文件内容。

-  "a" :以追加方式打开文件,如果文件不存在则创建,写入的数据会添加到文件末尾。

-  "r+" :以读写方式打开文件,文件必须存在。

-  "w+" :以读写方式打开文件,如果文件不存在则创建,如果存在则清空文件内容。

-  "a+" :以读和追加方式打开文件,如果文件不存在则创建。

 

 fopen  函数成功打开文件时返回一个  FILE  类型的指针,该指针用于后续对文件的读写操作。如果打开文件失败,则返回  NULL  。

在使用  fopen  后,务必在操作完成后使用  fclose  函数关闭文件,以释放相关资源。

 

例如:

#include <stdio.h>



int main() {

    FILE *fp;

    fp = fopen("example.txt", "w");

    if (fp == NULL) {

        printf("无法打开文件\n");

        return 1;

    }

    // 在这里进行文件写入操作

    fclose(fp);

    return 0;

}



 

fclose

在 C 语言中, fclose  函数用于关闭一个之前通过  fopen  函数打开的文件。

其函数原型为:

int fclose(FILE *stream);

 stream  是指向要关闭的文件的  FILE  指针。

 fclose  函数执行以下重要操作:

 

1. 刷新输出缓冲区中的数据,确保所有未写入的数据都被实际写入到文件中。

2. 释放与该文件相关的系统资源。

 fclose  函数返回 0 表示成功关闭文件,返回  EOF (通常定义为 -1)表示关闭文件时发生错误。

 

例如:

#include <stdio.h>



int main() {

    FILE *fp = fopen("test.txt", "w");

    if (fp == NULL) {

        printf("无法打开文件\n");

        return 1;

    }

    // 写入一些数据

    fprintf(fp, "这是一些测试数据");

    // 关闭文件

    if (fclose(fp) == EOF) {

        printf("关闭文件时出错\n");

        return 1;

    }

    return 0;

}

 

fgetc

在 C 语言中, fgetc  函数用于从指定的文件流中读取一个字符。
 
其函数原型为:

int fgetc(FILE *stream);


 stream  是指向要读取的文件流的  FILE  指针。
 
 fgetc  函数从文件流中读取下一个字符,并将其作为  unsigned char  类型的值转换为  int  类型后返回。如果到达文件末尾或发生读取错误,它将返回  EOF (通常定义为 -1)。
 
以下是一个简单的示例,展示如何使用  fgetc  函数读取文件中的字符:

#include <stdio.h>

int main() {
    FILE *fp;
    char ch;

    fp = fopen("example.txt", "r");
    if (fp == NULL) {
        printf("无法打开文件\n");
        return 1;
    }

    while ((ch = fgetc(fp))!= EOF) {
        putchar(ch);
    }

    fclose(fp);

    return 0;
}


在这个示例中,不断使用  fgetc  函数读取文件中的字符,并通过  putchar  函数输出到屏幕上,直到遇到文件末尾。
 

fputc

在 C 语言中, fputc  函数用于将一个字符写入到指定的文件流中。
 
其函数原型为:

int fputc(int c, FILE *stream);


 c  是要写入的字符(以  int  类型传递,实际存储的是字符的 ASCII 值)。 stream  是指向目标文件流的  FILE  指针。
 
 fputc  函数返回写入的字符,如果发生错误则返回  EOF  。
 
以下是一个使用  fputc  函数向文件写入字符的示例:

#include <stdio.h>

int main() {
    FILE *fp;

    fp = fopen("output.txt", "w");
    if (fp == NULL) {
        printf("无法打开文件\n");
        return 1;
    }

    fputc('H', fp);
    fputc('e', fp);
    fputc('l', fp);
    fputc('l', fp);
    fputc('o', fp);

    fclose(fp);

    return 0;
}


 
在这个示例中,依次向文件 "output.txt" 写入了字符 'H'、'e'、'l'、'l'、'o' 。
 
 

fgets

在 C 语言中, fgets  函数用于从指定的文件流中读取一行字符串。

其函数原型为:

char *fgets(char *str, int n, FILE *stream);

-  str  :指向用来存储读取字符串的字符数组。

-  n  :指定读取的最大字符数(包括最后的  '\0'  字符)。

-  stream  :指向要读取的文件流。

 

 fgets  函数从文件流中读取最多  n - 1  个字符,并在读取的字符串末尾添加  '\0'  作为字符串结束标志。如果在达到  n - 1  个字符之前遇到换行符  '\n'  或文件结束标志,读取操作也会停止。

如果成功读取到字符串(包括读到空行), fgets  函数返回  str  ;如果遇到文件结束或发生错误,则返回  NULL  。

以下是一个示例代码:

#include <stdio.h>



int main() {

    FILE *fp;

    char str[100];



    fp = fopen("example.txt", "r");

    if (fp == NULL) {

        printf("无法打开文件\n");

        return 1;

    }



    if (fgets(str, sizeof(str), fp)!= NULL) {

        printf("%s", str);

    }



    fclose(fp);



    return 0;

}

 

fputs

在 C 语言中, fputs  函数用于将一个字符串写入到指定的文件流中。

其函数原型为:

int fputs(const char *str, FILE *stream);

-  str  :要写入的字符串。

-  stream  :指向目标文件流的  FILE  指针。

 fputs  函数将字符串  str  写入到指定的文件流中,但它不会自动添加换行符。如果写入成功,函数返回一个非负值;如果发生错误,则返回  EOF  。

以下是一个简单的示例:

#include <stdio.h>



int main() {

    FILE *fp;



    fp = fopen("output.txt", "w");

    if (fp == NULL) {

        printf("无法打开文件\n");

        return 1;

    }



    fputs("这是写入的字符串", fp);



    fclose(fp);



    return 0;

}

 

fwrite

在 C 语言中, fwrite  函数用于将数据块写入到指定的文件流中。

其函数原型为:

size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);

-  ptr :指向要写入数据的指针。

-  size :每个数据项的大小(以字节为单位)。

-  nmemb :要写入的数据项的数量。

-  stream :指向目标文件流的  FILE  指针。

 fwrite  函数返回实际写入的数据项的数量。如果返回值小于  nmemb  ,则表示发生了错误。

以下是一个示例代码,展示如何使用  fwrite  函数写入数据:

#include <stdio.h>



int main() {

    FILE *fp;

    int data[] = {1, 2, 3, 4, 5};



    fp = fopen("data.bin", "wb");

    if (fp == NULL) {

        printf("无法打开文件\n");

        return 1;

    }



    size_t written = fwrite(data, sizeof(int), sizeof(data) / sizeof(int), fp);



    if (written!= sizeof(data) / sizeof(int)) {

        printf("写入错误\n");

    }



    fclose(fp);



    return 0;

}



在这个示例中,将一个整数数组写入到二进制文件中。

 

fread

在 C 语言中, fread  函数用于从指定的文件流中读取数据块。

其函数原型为:

size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);

-  ptr :指向用于存储读取数据的内存缓冲区的指针。

-  size :每个数据项的大小(以字节为单位)。

-  nmemb :要读取的数据项的数量。

-  stream :指向要读取的文件流的  FILE  指针。

 

 fread  函数返回实际读取到的数据项的数量。如果返回值小于  nmemb  ,可能表示到达了文件末尾或者发生了错误。

 

以下是一个简单的示例,展示如何使用  fread  函数读取数据:

#include <stdio.h>



int main() {

    FILE *fp;

    int data[5];



    fp = fopen("data.bin", "rb");

    if (fp == NULL) {

        printf("无法打开文件\n");

        return 1;

    }



    size_t read = fread(data, sizeof(int), 5, fp);



    if (read!= 5) {

        printf("读取错误或未读取到完整数据\n");

    }



    fclose(fp);



    // 打印读取到的数据

    for (int i = 0; i < 5; i++) {

        printf("%d ", data[i]);

    }

    printf("\n");



    return 0;

}

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值