青海城乡和住房建设厅网站/网店seo

青海城乡和住房建设厅网站,网店seo,抚州建设网站,网络设计的安全性原则主要是指目录 一、重定向的原理与实践 1. 输出重定向:让数据流向新目的地 2. 追加重定向:在文件末尾追加数据 3. 输入重定向:从指定文件读取数据 4. 标准输出流与标准错误流的区别 5. 使用 dup2 实现重定向 二、FILE 结构体的奥秘 1. FILE 中的…

目录

一、重定向的原理与实践

1. 输出重定向:让数据流向新目的地

2. 追加重定向:在文件末尾追加数据

3. 输入重定向:从指定文件读取数据

4. 标准输出流与标准错误流的区别

5. 使用 dup2 实现重定向

二、FILE 结构体的奥秘

1. FILE 中的文件描述符

2. FILE 中的缓冲区

3. 缓冲区的提供者与位置

4. 操作系统的缓冲区

5. 缓冲体系的层级架构

​编辑


一、重定向的原理与实践

1. 输出重定向:让数据流向新目的地

原理

        输出重定向的本质是修改文件描述符下标对应的 struct file* 内容,将原本应该输出到一个文件(通常是显示器)的数据,改为输出到另一个文件。

代码示例

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>int main() {// 关闭标准输出流(文件描述符 1)close(1);// 打开 log.txt 文件,获取文件描述符int fd = open("log.txt", O_WRONLY | O_CREAT, 0666);if (fd < 0) {perror("open");return 1;}// 使用 printf 输出数据printf("hello world\n");printf("hello world\n");printf("hello world\n");printf("hello world\n");printf("hello world\n");// 刷新缓冲区,确保数据写入文件fflush(stdout);// 关闭文件描述符close(fd);return 0;
}

运行结果 :运行程序后,显示器上没有输出数据,而 log.txt 文件中写入了多行 "hello world"。

说明printf 函数默认向标准输出流(stdout)输出数据,而 stdout 指向的 FILE 结构体中存储的文件描述符是 1。通过关闭文件描述符 1 并重新打开文件,我们实现了输出重定向。

2. 追加重定向:在文件末尾追加数据

原理

        追加重定向与输出重定向类似,区别在于数据是追加到目标文件末尾,而不是覆盖原有内容。通过O_APPEND标志,每次写入都会自动定位到文件末尾,保留原有内容。

代码示例

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>int main() {// 关闭标准输出流(文件描述符 1)close(1);// 以追加方式打开 log.txt 文件int fd = open("log.txt", O_WRONLY | O_APPEND | O_CREAT, 0666);if (fd < 0) {perror("open");return 1;}// 使用 printf 输出数据printf("hello Linux\n");printf("hello Linux\n");printf("hello Linux\n");printf("hello Linux\n");printf("hello Linux\n");// 刷新缓冲区,确保数据写入文件fflush(stdout);// 关闭文件描述符close(fd);return 0;
}

运行结果 :运行程序后,log.txt 文件中新增了多行 "hello Linux",且这些内容追加在原有内容之后。

3. 输入重定向:从指定文件读取数据

原理

        输入重定向是将原本从标准输入流(通常是键盘)读取数据的操作,改为从指定文件读取数据。

代码示例

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>int main() {// 关闭标准输入流(文件描述符 0)close(0);// 打开 log.txt 文件,获取文件描述符int fd = open("log.txt", O_RDONLY | O_CREAT, 0666);if (fd < 0) {perror("open");return 1;}// 定义字符数组,用于存储读取的数据char str[40];// 使用 scanf 从文件读取数据while (scanf("%s", str) != EOF) {printf("%s\n", str);}// 关闭文件描述符close(fd);return 0;
}

运行结果 :运行程序后,scanf 函数从 log.txt 文件中读取数据,并通过 printf 输出到显示器。

说明scanf 函数默认从标准输入流(stdin)读取数据,而 stdin 指向的 FILE 结构体中存储的文件描述符是 0。通过关闭文件描述符 0 并重新打开文件,我们实现了输入重定向。

4. 标准输出流与标准错误流的区别

原理

        标准输出流(stdout,文件描述符 1)和标准错误流(stderr,文件描述符 2)都默认输出到显示器,但它们在重定向时的行为不同。重定向操作只影响标准输出流,而标准错误流不受影响。

操作stdout表现stderr表现
直接运行屏幕输出屏幕输出
重定向到文件写入文件仍显示屏幕

代码示例

#include <stdio.h>int main() {// 向标准输出流输出数据printf("hello printf\n");// 向标准错误流输出数据perror("perror");// 使用 fprintf 向标准输出流和标准错误流输出数据fprintf(stdout, "stdout:hello fprintf\n");fprintf(stderr, "stderr:hello fprintf\n");return 0;
}

运行结果 :直接运行程序时,显示器上输出四行字符串。若将程序运行结果重定向到文件 log.txt,则 log.txt 中只有标准输出流的两行字符串,而标准错误流的两行数据仍输出到显示器。

5. 使用 dup2 实现重定向

原理

dup2 函数用于将一个文件描述符的内容拷贝到另一个文件描述符,从而实现重定向。

函数原型

int dup2(int oldfd, int newfd);

代码示例

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>int main() {// 打开 log.txt 文件,获取文件描述符int fd = open("log.txt", O_WRONLY | O_CREAT, 0666);if (fd < 0) {perror("open");return 1;}// 关闭标准输出流(文件描述符 1)close(1);// 使用 dup2 将 fd 拷贝到文件描述符 1// 将log.txt克隆到标准输出dup2(fd, 1);// 使用 printf 输出数据// 自动写入log.txtprintf("hello printf\n");fprintf(stdout, "hello fprintf\n");// 关闭文件描述符close(fd);return 0;
}

运行结果 :运行程序后,log.txt 文件中写入了 "hello printf" 和 "hello fprintf"。

二、FILE 结构体的奥秘

1. FILE 中的文件描述符

原理

        C 语言的库函数是对系统调用接口的封装,文件操作本质上是通过文件描述符进行的。FILE 结构体内部封装了文件描述符。

/usr/include/stdio.h 头文件中,FILEstruct _IO_FILE 的别名。

typedef struct _IO_FILE FILE;

/usr/include/libio.h 头文件中,struct _IO_FILE 定义了 _fileno 成员,用于存储文件描述符。

struct _IO_FILE {int _flags;       /* High-order word is _IO_MAGIC; rest is flags. */
#define _IO_file_flags _flags//缓冲区相关/* The following pointers correspond to the C++ streambuf protocol. *//* Note:  Tk uses the _IO_read_ptr and _IO_read_end fields directly. */char* _IO_read_ptr;   /* Current read pointer */char* _IO_read_end;   /* End of get area. */char* _IO_read_base;  /* Start of putback+get area. */char* _IO_write_base; /* Start of put area. */char* _IO_write_ptr;  /* Current put pointer. */char* _IO_write_end;  /* End of put area. */char* _IO_buf_base;   /* Start of reserve area. */char* _IO_buf_end;    /* End of reserve area. *//* The following fields are used to support backing up and undo. */char *_IO_save_base; /* Pointer to start of non-current get area. */char *_IO_backup_base;  /* Pointer to first valid character of backup area */char *_IO_save_end; /* Pointer to end of non-current get area. */struct _IO_marker *_markers;struct _IO_FILE *_chain;int _fileno; //封装的文件描述符
#if 0int _blksize;
#elseint _flags2;
#endif_IO_off_t _old_offset; /* This used to be _offset but it's too small.  */#define __HAVE_COLUMN /* temporary *//* 1+column number of pbase(); 0 is unknown. */unsigned short _cur_column;signed char _vtable_offset;char _shortbuf[1];/*  char* _save_gptr;  char* _save_egptr; */_IO_lock_t *_lock;
#ifdef _IO_USE_OLD_IO_FILE
};

示例代码

#include <stdio.h>int main() {FILE *fp = fopen("test.txt", "w");if (fp == NULL) {perror("fopen");return 1;}// 获取 FILE 结构体中的文件描述符int fd = fileno(fp);// 使用文件描述符进行操作// ...// 关闭文件fclose(fp);return 0;
}

说明fopen 函数在上层为用户申请 FILE 结构体变量,并返回该结构体的地址。在底层通过系统接口 open 打开文件,得到文件描述符,并将其存储在 FILE 结构体的 _fileno 成员中。

2. FILE 中的缓冲区

原理

        C 语言中的文件操作函数(如 printffputs 等)使用缓冲区来提高效率。缓冲区的类型有无缓冲、行缓冲和全缓冲。

缓冲类型对比表

缓冲类型刷新条件典型应用场景
无缓冲立即写入标准错误
行缓冲遇换行符或缓冲区满终端输出
全缓冲缓冲区满或强制刷新文件操作

代码示例

#include <stdio.h>
#include <unistd.h>int main() {// 使用 printf 输出数据printf("hello printf\n");// 使用 fputs 输出数据fputs("hello fputs\n", stdout);// 使用 write 系统接口输出数据write(1, "hello write\n", 12);// 创建子进程fork();return 0;
}

运行结果 :直接运行程序时,数据输出到显示器。若将程序运行结果重定向到文件 log.txt,则 log.txtprintffputs 的数据出现两次,而 write 的数据只出现一次。

说明printffputs 使用缓冲区,当程序运行结果重定向到文件时,缓冲区的数据会被复制到父进程和子进程中,导致数据重复。而 write 是系统接口,没有缓冲区,数据直接输出到目标文件。

3. 缓冲区的提供者与位置

原理

        缓冲区由 C 语言提供,在 FILE 结构体中维护。FILE 结构体中包含多个成员,用于记录缓冲区的相关信息。

/usr/include/libio.h 头文件中,struct _IO_FILE 定义了多个与缓冲区相关的成员,如 _IO_read_ptr_IO_read_end 等。

//缓冲区相关
/* The following pointers correspond to the C++ streambuf protocol. */
/* Note:  Tk uses the _IO_read_ptr and _IO_read_end fields directly. */
char* _IO_read_ptr;   /* Current read pointer */
char* _IO_read_end;   /* End of get area. */
char* _IO_read_base;  /* Start of putback+get area. */
char* _IO_write_base; /* Start of put area. */
char* _IO_write_ptr;  /* Current put pointer. */
char* _IO_write_end;  /* End of put area. */
char* _IO_buf_base;   /* Start of reserve area. */
char* _IO_buf_end;    /* End of reserve area. */
/* The following fields are used to support backing up and undo. */
char *_IO_save_base; /* Pointer to start of non-current get area. */
char *_IO_backup_base;  /* Pointer to first valid character of backup area */
char *_IO_save_end; /* Pointer to end of non-current get area. */

示例代码

#include <stdio.h>int main() {FILE *fp = fopen("test.txt", "w");if (fp == NULL) {perror("fopen");return 1;}// 使用 fputs 写入数据fputs("hello fputs", fp);// 刷新缓冲区fflush(fp);// 关闭文件fclose(fp);return 0;
}

说明fputs 函数将数据写入 FILE 结构体中的缓冲区,fflush 函数用于刷新缓冲区,将数据写入文件。

4. 操作系统的缓冲区

原理

        操作系统也有自己的缓冲区。当用户缓冲区的数据被刷新到操作系统缓冲区后,操作系统会根据自己的刷新机制,将数据写入磁盘或显示器。

示例代码

#include <stdio.h>
#include <unistd.h>int main() {// 使用 printf 输出数据printf("hello printf\n");// 刷新用户缓冲区fflush(stdout);// 暂停 2 秒sleep(2);return 0;
}

说明printf 输出的数据先存储在用户缓冲区,fflush 刷新用户缓冲区后,数据进入操作系统缓冲区。操作系统会根据自己的刷新机制,将数据写入显示器。

5. 缓冲体系的层级架构

数据流动路径:

用户程序 → C库缓冲区(用户空间)→ 内核缓冲区(内核空间)→ 物理存储设备

关键特点

  • 用户缓冲区由C库维护

  • 内核缓冲区由OS管理

  • fflush只刷新用户→内核阶段

  • 最终落盘由内核决定

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/71511.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

DeepSeek 冲击(含本地化部署实践)

DeepSeek无疑是春节档最火爆的话题&#xff0c;上线不足一月&#xff0c;其全球累计下载量已达4000万&#xff0c;反超ChatGPT成为全球增长最快的AI应用&#xff0c;并且完全开源。那么究竟DeepSeek有什么魔力&#xff0c;能够让大家趋之若鹜&#xff0c;他又将怎样改变世界AI格…

显微镜下的人体结构

显微镜下的人体结构&#xff0c;看完以后&#xff0c;你还觉得人类是进化而来的吗&#xff1f;...... 第一张&#xff1a;电子显微镜所观察到的人类血管&#xff0c;可以非常清楚的看到里面的白细胞和红细胞 第二张&#xff1a;正在分泌耳垢&#xff08;耳屎&#xff09;的耳道…

DApp 开发入门指南

DApp 开发入门指南 &#x1f528; 1. DApp 基础概念 1.1 什么是 DApp&#xff1f; 去中心化应用&#xff08;DApp&#xff09;是基于区块链的应用程序&#xff0c;特点是&#xff1a; 后端运行在区块链网络前端可以是任何框架使用智能合约处理业务逻辑数据存储在区块链上 1…

LabVIEW开发中的电机控制与相机像素差

在电机控制系统中&#xff0c;我们需要精确控制电机运动与相机拍摄画面之间的关系。理想情况下&#xff0c;当电机带动相机移动同样的距离时&#xff0c;相机拍摄画面中两点之间的像素差应当是一个固定值。然而&#xff0c;在实际应用中&#xff0c;我们发现这一像素差并非固定…

【DeepSeek】Mac m1电脑部署DeepSeek

一、电脑配置 个人电脑配置 二、安装ollama 简介&#xff1a;Ollama 是一个强大的开源框架&#xff0c;是一个为本地运行大型语言模型而设计的工具&#xff0c;它帮助用户快速在本地运行大模型&#xff0c;通过简单的安装指令&#xff0c;可以让用户执行一条命令就在本地运…

【Dubbo+Zookeeper】——SpringBoot+Dubbo+Zookeeper知识整合

&#x1f3bc;个人主页&#xff1a;【Y小夜】 &#x1f60e;作者简介&#xff1a;一位双非学校的大二学生&#xff0c;编程爱好者&#xff0c; 专注于基础和实战分享&#xff0c;欢迎私信咨询&#xff01; &#x1f386;入门专栏&#xff1a;&#x1f387;【MySQL&#xff0…

【OS安装与使用】part5-ubuntu22.04基于conda安装pytorch+tensorflow

文章目录 一、待解决问题1.1 问题描述1.2 解决方法 二、方法详述2.1 必要说明2.2 应用步骤2.2.1 明确pytorch安装依赖2.2.2 conda创建虚拟环境2.2.3 安装pytorch2.2.4 验证pytorch安装2.2.5 安装Tensorflow2.2.6 验证Tensorflow安装 三、疑问四、总结 一、待解决问题 1.1 问题…

计算机网络:应用层 —— 动态主机配置协议 DHCP

文章目录 什么是 DHCP&#xff1f;DHCP 的产生背景DHCP 的工作过程工作流程地址分配机制 DHCP 中继代理总结 什么是 DHCP&#xff1f; 动态主机配置协议&#xff08;DHCP&#xff0c;Dynamic Host Configuration Protocol&#xff09;是一种网络管理协议&#xff0c;用于自动分…

【OS安装与使用】part3-ubuntu安装Nvidia显卡驱动+CUDA 12.4

文章目录 一、待解决问题1.1 问题描述1.2 解决方法 二、方法详述2.1 必要说明2.2 应用步骤2.2.1 更改镜像源2.2.2 安装NVIDIA显卡驱动&#xff1a;nvidia-550&#xff08;1&#xff09;查询显卡ID&#xff08;2&#xff09;PCI ID Repository查询显卡型号&#xff08;3&#xf…

数据导入AI训练步骤——人工智能训练

一、人工操作转化 数据导入过程 整理excel表格&#xff0c;通过数据库管理工具导入数据&#xff0c;补充数据格式&#xff0c;调整sql语句 复制数据到目标数据 二、整理表格 三、导入数据 通过数据库导入数据 四、合并 五、验证更新数据 六、 更新数据 update temp_cus_hmz…

我国首条大型无人机城际低空物流航线成功首航

首航震撼开场&#xff1a;羊肉 “飞” 越 540 公里 在夜色的笼罩下&#xff0c;榆阳马合通用机场的跑道上&#xff0c;一架大型固定翼无人机蓄势待发&#xff0c;机身被灯光照亮&#xff0c;宛如一只即将展翅翱翔的钢铁巨鸟。它的货舱里&#xff0c;满满装载着新鲜的榆林羊肉&a…

《跟李沐学 AI》AlexNet论文逐段精读学习心得 | PyTorch 深度学习实战

前一篇文章&#xff0c;使用 AlexNet 实现图片分类 | PyTorch 深度学习实战 本系列文章 GitHub Repo: https://github.com/hailiang-wang/pytorch-get-started 本篇文章内容来自于学习 9年后重读深度学习奠基作之一&#xff1a;AlexNet【下】【论文精读】】的心得。 《跟李沐…

微软Win11新动态:官方“换机助手”曝光,PC数据迁移或迎全新体验

目录 微软入局数据迁移领域,第三方工具或面临挑战 无缝迁移体验:近距离传输与OTP验证 模拟图仅为概念设计,最终功能或存变数 发布时间未定,Insider用户或率先体验 总结 微软在近期发布了Windows 11 Insider Beta频道的最新版本Build 22635.4945。尽管此次更新并未引入重…

java练习(34)

ps:题目来自力扣 寻找两个正序数组的中位数 给定两个大小分别为 m 和 n 的正序&#xff08;从小到大&#xff09;数组 nums1 和 nums2。请你找出并返回这两个正序数组的 中位数 。 算法的时间复杂度应该为 O(log (mn)) 。 class Solution {public double findMedianSortedA…

DAY12 Tensorflow 六步法搭建神经网络

六步法&#xff1a; 一.import 导入各种库&#xff0c;比如&#xff1a; import tensorflow as tf from tensorflow.keras.layers import Dense, Flatten from tensorflow.keras import Model import numpy as np import pandas as pd # 可能还会根据需求导入其他库&…

Zookeeper分布式锁实现

zookeeper最初设计的初衷就是为了保证分布式系统的一致性。本文将讲解如何利用zookeeper的临时顺序结点&#xff0c;实现分布式锁。 目录 1. 理论分析 1.1 结点类型 1.2 监听器 1.3 实现原理 2. 手写实现简易zookeeper分布式锁 1.1 依赖 1.2 常量定义 1.3 实现zookeeper分布式…

Git是什么

简单介绍&#xff1a; Git是一个分布式版本控制系统&#xff0c;用于跟踪文件的更改&#xff0c;特别是在多人协作开发的环境中。 Key: 分布式 版本控制 系统 最常用于软件开发&#xff0c;但也可以用于管理任何类型的文件和文件夹。 Git帮助团队跟踪和管理文件的历史版本&a…

Pycharm 2024在解释器提供的python控制台中运行py文件

2024版的界面发生了变化, run with python console搬到了这里:

【分布式理论12】事务协调者高可用:分布式选举算法

文章目录 一、分布式系统中事务协调的问题二、分布式选举算法1. Bully算法2. Raft算法3. ZAB算法 三、小结与比较 一、分布式系统中事务协调的问题 在分布式系统中&#xff0c;常常有多个节点&#xff08;应用&#xff09;共同处理不同的事务和资源。前文 【分布式理论9】分布式…

免费deepseek的API获取教程及将API接入word或WPS中

免费deepseek的API获取教程: 1 https://cloud.siliconflow.cn/中注册时填写邀请码&#xff1a;GAejkK6X即可获取2000 万 Tokens; 2 按照图中步骤进行操作 将API接入word或WPS中 1 打开一个word&#xff0c;文件-选项-自定义功能区-勾选开发工具-左侧的信任中心-信任中心设置…