合肥网站制作企业/关键字排名查询工具

合肥网站制作企业,关键字排名查询工具,moodle ual wordpress,深圳优定软件网站建设目录 一、文件描述符 1.文件内核对象 2.文件描述符分配原则 二、文件重定向 1.重定向的现象 输出重定向 输入重定向 dup2 2.重定向的使用 三、标准输出和标准错误 继上篇文章中,我们了解了fd打印的值为文件描述符,那么它还有什么作用呢&…

目录

 一、文件描述符

1.文件内核对象 

2.文件描述符分配原则

二、文件重定向

1.重定向的现象

输出重定向

输入重定向 

dup2

2.重定向的使用

三、标准输出和标准错误 


继上篇文章中,我们了解了fd打印的值为文件描述符,那么它还有什么作用呢? 

 一、文件描述符

1.文件内核对象 

我们学习了open函数,知道了文件描述符就是一个整数。Linux 进程默认情况下会有 3 个缺省打开的文件描述符,分别是标准输入 0, 标准输出 1, 标准错误 2。0、1、2 对应的物理设备一般是:键盘显示器显示器

ssize_t read(int fd, void *buf, size_t count);
ssize_t write(int fd, const void *buf, size_t count);

输入输出程序: 

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>int main()
{char buf[1024];// 定义一个1024字节的缓冲区ssize_t s = read(0, buf, sizeof(buf));//从标准输入(stdin)读取数据到缓冲区bufif(s > 0)// 检查是否成功读取到数据{buf[s] = 0; // 手动添加字符串终止符'\0'write(1, buf, strlen(buf));// 将数据写入标准输出write(2, buf, strlen(buf));// 将数据写入标准错误//write() 是直接写入内核,无需手动刷新缓冲区。}return 0;
}

运行后,输出一个yes,就会再往显示屏打印两个yes 

 

write是如何通过fd找到要打印的文件的呢?  

重新理解文件描述符表:


站在用户的角度,对于文件的操作有这些诸如read、write这些系统调用,也有这些系统调用进行了一定的封装后诞生的C语言库函数,这些系统调用的内部会在内存中进行一系列操作,当程序运行的时候,进程里有个叫PCB的结构体,进程的PCB中有这么一块专门的区域名字叫作fd_array[],它的本质是一个指针数组,它会指向一个一个结构体,而每一个结构体中存储的是关于这个文件的信息,这个结构体叫做struct file,而前面所说的文件描述符fd,本质上就是这个指针数组的下标。系统默认会打开三个文件:标准输入、输出和错误。比如你调用read或write的时候,系统会根据fd找到对应的file结构体,然后操作对应文件。不过数据读写不是直接和硬盘打交道的——因为CPU只能和内存玩,所以读写前得把数据先从硬盘加载到内存里的文件缓冲区里,进程才能从中读写。不管读还是写,都是在内核缓冲区和用户空间之间倒腾数据,这也就是为什么系统调用看起来像是在内存里搞事情的原因啦。 结论:在应用层对于数据的读写,本质上是将内核缓冲区的数据进行来回拷贝。

2.文件描述符分配原则

我们知道因为系统会默认打开三个文件,分别占用0,1,2这三个位置, 那么把前面这几个关掉呢?

关闭0: 

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>int main()
{close(0);int fd = open("log.txt", O_WRONLY|O_CREAT|O_TRUNC, 0666);if(fd < 0){perror("open");return 1;}printf("fd: %d\n", fd);close(fd);return 0;
}

运行结果(关闭2也是一样的效果):

 

由此可以推测出,文件描述符的分配规则是:寻找最小的,没有被使用的数据的位置,分配给指定的打开文件 

二、文件重定向

1.重定向的现象

刚刚其实我们已经细微的发现了重定向了,但是现在我们将要学的更加细:

输出重定向

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>// 重定向
void test()
{close(1);int fd = open("log.txt", O_CREAT | O_WRONLY | O_TRUNC, 0666);if(fd < 0){perror("open fail\n");exit(1);}printf("fd-> %d\n", fd);printf("stdout->fd: %d\n", stdout->_fileno);fflush(stdout);close(fd);
}int main()
{test();return 0;
}

 运行结果:

 

运行结果是,在屏幕上没有任何信息,但在log.txt中居然出现了输出信息。 

当程序通过关闭标准输出(fd=1)并重新打开一个文件(如log.txt)时,由于文件描述符遵循"用完即丢"的复用规则,新文件会抢占原本属于标准输出的1号索引位置。此时所有以1为默认目标的输出操作(包括printf)都会被悄悄重定向——它们不再往显示器写数据,而是像对待普通文件一样向log.txt写入内容。这个过程中,Linux内核通过VFS将设备抽象成统一的文件对象,使得无论stdout原本指向的是屏幕还是磁盘文件,最终都表现为对特定文件描述符的操作。这种设计巧妙利用了文件描述符的索引特性,实现了I/O重定向的核心逻辑:系统只认数字标号,不关心具体绑定的物理设备,真正实现了"一切皆文件"的统一管理理念总结:新打开的文件描述符取代了stdout原先的描述符,大家只认fd==1的文件。 

输入重定向 

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>int main()
{close(0);int fd = open("log.txt", O_RDONLY);if (fd < 0){perror("open");return 1;}printf("fd: %d\n", fd);char buf[64];fgets(buf, sizeof buf, stdin);printf("%s", buf);return 0;
}

 

重定向的本质,就是修改特征文件fd的下标内容。上层的fd不变,变化的是底层fd指向的内容,也就是所谓文件描述符级别的数组内容的拷贝。那这样的写法还是太奇怪了,每次都要把一个文件关闭再打开一个新的文件,作为系统理应给操作者提供这样替换文件描述符的系统调用,事实上也确实提供了这样的系统调用。 

dup2

SYNOPSIS#include <unistd.h>int dup(int oldfd);int dup2(int oldfd, int newfd);
*  If oldfd is not a valid file descriptor, then the call fails, and newfd is not closed.
*  If oldfd is a valid file descriptor, and newfd has the same value as oldfd, then dup2() does nothing, and returns newfd.

简单来说,就是用oldfd去替换newfd,保留下来的是oldfd,那么上面的代码就可以被改良成这样:

void redir2()
{int fd = open("log.txt", O_CREAT | O_WRONLY | O_APPEND, 0666);if(fd < 0){perror("open fail\n");exit(1);}dup2(fd, 1);printf("fd-> %d\n", fd);printf("stdout->fd: %d\n", stdout->_fileno);fflush(stdout);close(fd);
}

运行结果: 

 

fd->3,fd也没有变化,但是就是没有往显示屏上打印,依旧是往文件里打印的。也就是说,不需要你去关闭一个文件秒速符,而是用一个文件描述符暂时的代替另外一个文件描述符,这样不仅更加准确,而且更加明了。

要输出的文件描述符是 1,而要重定向的目标文件描述符是 fd (echo “hello” > log.txt),dup2 应该怎么传参 —— dup2(1, fd) || dup2(fd, 1) ? 

*  If oldfd is not a valid file descriptor, then the call fails, and newfd is not closed.
*  If oldfd is a valid file descriptor, and newfd has the same value as oldfd, then dup2() does nothing, and returns newfd.

很明显依靠函数原型,我们就能认为 dup2(1, fd),因为 1 是先打开的,而 fd 是后打开的.可实际上并不是这样的,文档中说 newfd 是 oldfd 的一份拷贝,这里拷贝的是文件描述符对应数组下标的内容,所以数组内容最终应该和 oldfd 一致。换而言之,这里就是想把让 1 不要指向显示器了,而指向 log.txt,fd 也指向 log.txt。所以这里的 oldfd 对应 fd,newfd 对应 1,所以应该是 dup2(fd, 1)。

oldfd copy to newfd -> 最后要和谁一样? oldfd

假设输出重定向:显示器(1) -> log.txt(3)。应该是 dup2(1, 3);,还是dup2(3, 1); ?

dup2(3, 1);

3 的内容 copy 到 1 里面 -> 最终和 3 一致

2.重定向的使用

 重定向其实并不陌生,在之前的学习中已经用过重定向,只是那是还没有建立起来一个基础的概念,先看下面的指令演示:

[root@iZbp1157ft1ib0ydj8jqtzZ test]# echo "hello linux" > log.txt
[root@iZbp1157ft1ib0ydj8jqtzZ test]# cat log.txt
hello linux

这段指令的含义就是,把hello linux重定向到log.txt中,其实这样的操作符还有下面的这几种,一一进行介绍

>:这个操作符表示的是输出重定向,意思就是把内容输出到某个文件中,有些类似于以w的方式打开一个文件并进行写入。

>>:这个操作符表示的是追加重定向,意思就是把内容追加输出到某个文件中,有些类似于append的方式进行写入。

<:这个操作符表示的是输入重定向,表示把原来的内容输入输入到某个文件中,相当于是替换了标准输入流的文件。

三、标准输出和标准错误 

前面的知识已经足以理解为什么要有标准输入和标准输出,但是还有一个问题有待解决,标准错误的意义是什么呢?难道标准输出的信息还不够吗?

答案是确实不够,在对于大型项目的时候,会有很多的输出信息,这些输出信息有些是正常信息,有些是异常信息,而对于开发者来说他们需要的是错误信息,因此对于如何获取错误信息就显得至关重要,于是标准错误流信息就诞生了,对于正常来说可能没有太多的感觉,但是实际上,没有感觉的原因是因为标准错误和标准输出的文件对象都是显示器,而实际上这是可以被替换的,基于这个原理可以做出下面的测试代码:

int main()
{printf("this is normal message\n");perror("this is error message\n");return 0;
}

 运行和操作结果:

[root@iZbp1157ft1ib0ydj8jqtzZ test]# ./test 1>out.txt 2>error.txt
[root@iZbp1157ft1ib0ydj8jqtzZ test]# cat out.txt
this is normal message
[root@iZbp1157ft1ib0ydj8jqtzZ test]# cat error.txt
this is error message
: Success

利用上面的原理可以写出这样的测试代码,把正确信息存储到一个文件中,把错误信息存储到另外一个文件中,这样就能知道哪里是错误哪里是正确了。

1>&2意思是把标准输出重定向到标准错误。

2>&1意思是把标准错误输出重定向到标准输出。

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

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

相关文章

CentOS 7 安装Nginx-1.26.3

无论安装啥工具、首先认准了就是官网。Nginx Nginx官网下载安装包 Windows下载&#xff1a; http://nginx.org/download/nginx-1.26.3.zipLinxu下载 wget http://nginx.org/download/nginx-1.26.3.tar.gzLinux安装Nginx-1.26.3 安装之前先安装Nginx依赖包、自行选择 yum -y i…

笔记:如何使用XAML Styler以及在不同的开发环境中使用一致

一、目的&#xff1a;分享如何使用XAML Styler以及在不同的开发环境中使用一致 XAML Styler 是一个 Visual Studio 扩展&#xff0c;用于自动格式化和整理 XAML 文件。它可以帮助开发者保持一致的代码风格&#xff0c;提高代码的可读性和可维护性。以下是如何在 Visual Studio …

分布式存储学习——HBase概述

1.1 HBase概述 1.1.1 理解大数据背景 1.1.2 HBase是什么 1.1.3 HBase与Hadoop的关系 1.1.4 HBase的核心功能模块 1.1.5 HBase的应用场景和经典案例 1.1.6 小结 本文参考于学校《HBase应用于开发》教材 1.1 HBase概述 本节将介绍大数据背景和HBase的基本概念&#xff0c…

交叉编译openssl及curl

操作环境&#xff1a;Ubuntu20.04 IDE工具&#xff1a;Clion2020.2 curl下载地址&#xff1a;https://curl.se/download/ openssl下载地址&#xff1a;https://openssl-library.org/source/old/index.html 直接交叉编译curl会报错找不到openssl&#xff0c;所以需要先交叉编…

零基础C语言学习日志22(自定义类型:联合和枚举)

目录 联合体 联合体类型的声明 联合体的特点 相同成员联合体和结构体的对比 联合体大小的计算 例子 枚举类型 枚举类型的声明 枚举类型的优点 枚举类型的使用 联合体 联合体类型的声明 像结构体一样&#xff0c;联合体也是由一个或者多个成员构成&#xff0c;这些成…

天津大学02-深度解读DeepSeek:部署、使用、安全【文末附下载链接】

大模型风险与不当用例——价值观错位 大模型与人类价值观、期望之间的不一致而导致的安全问题&#xff0c;包含&#xff1a;• 社会偏见&#xff08;Social Bias&#xff09;LLM在生成文本时强化对特定社会群体的刻板印象&#xff0c;例如将穆斯林与恐怖主义关联&#xff0c;或…

[C语言日寄] 字符串操作函数的使用及其拓展

【作者主页】siy2333 【专栏介绍】⌈c语言日寄⌋&#xff1a;这是一个专注于C语言刷题的专栏&#xff0c;精选题目&#xff0c;搭配详细题解、拓展算法。从基础语法到复杂算法&#xff0c;题目涉及的知识点全面覆盖&#xff0c;助力你系统提升。无论你是初学者&#xff0c;还是…

Qt 进度条与多线程应用、基于 Qt 的文件复制工具开发

练习1&#xff1a;Qt 进度条与多线程应用 题目描述 开发一个基于 Qt 的应用程序&#xff0c;该应用程序包含一个水平进度条&#xff08;QSlider&#xff09;&#xff0c;并且需要通过多线程来更新进度条的值。请根据以下要求完成代码&#xff1a; 界面设计&#xff1a; 使用 QS…

Gartner:数据安全平台DSP提升数据流转及使用安全

2025 年 1 月 7 日&#xff0c;Gartner 发布“China Context&#xff1a;Market Guide for Data Security Platforms”&#xff08;《数据安全平台市场指南——中国篇》&#xff0c;以下简称指南&#xff09;&#xff0c;报告主要聚焦中国数据安全平台&#xff08;Data Securit…

解决:Word 保存文档失败,重启电脑后,Word 在试图打开文件时遇到错误

杀千刀的微软&#xff0c;设计的 Word 是个几把&#xff0c;用 LaTex 写完公式&#xff0c;然后保存&#xff0c;卡的飞起 我看文档卡了很久&#xff0c;就关闭文档&#xff0c;然后 TMD 脑抽了重启电脑 重启之后&#xff0c;文档打不开了&#xff0c;显示 杀千刀的&#xff…

掌握高效大模型任务流搭建术(二):链式流程如何赋能 AI 处理能力提升

前言&#xff1a; 在上一篇文章中&#xff0c;我们初步探索了 LangChain 的基础链式操作——LLMChain。它巧妙地将大语言模型&#xff08;LLM&#xff09;与提示模板&#xff08;Prompt Template&#xff09;相结合&#xff0c;为模型交互逻辑的封装提供了一种简洁而高效的方式…

虚拟卡 WildCard (野卡) 保姆级开卡教程

本文首发于只抄博客&#xff0c;欢迎点击原文链接了解更多内容。 前言 本篇教程为 WildCard 的介绍以及开卡教学&#xff0c;要了解不同平台&#xff08;Grok、Talkatone 等&#xff09;的订阅方式请移步《订阅教程》分类 当我们想要充值国外平台会员时&#xff0c;一般都需要使…

记录一些面试遇到的问题

重载和重写的区别 重载是overload&#xff0c;覆盖是override 重载属于编译时多态&#xff0c;覆盖属于运行时多态 运行时多态和编译时多态 运行时多态指的是在运行的时候才知道要调用哪一个函数&#xff0c;编译时多态是指在编译的时候就知道调用哪一个函数。 运行时多态…

HBuilder X 使用 TortoiseSVN 设置快捷键方法

HBuilder X 使用 TortoiseSVN 设置快捷键方法 单文件&#xff1a;(上锁&#xff0c;解锁&#xff0c;提交&#xff0c;更新) 安装好 TortoiseSVN &#xff0c;或者 按图操作&#xff1a; 1&#xff0c;工具栏中 【自定义快捷键】 2&#xff0c;点击 默认的快捷键设置&…

JmeterHttp请求头管理出现Unsupported Media Type问题解决

JmeterHttp请求头管理出现Unsupported Media Type问题解决 大多数的app与pc端压测的时候都会出现这种情况 当我们在jemter测试当中当中遇见Unsupported Media Type&#xff0c;有一种可能就是我们请求的网页的content-Type的类型与我们测试的时候的类型不一致 解决方法 可以添…

尚硅谷爬虫note14

一、scrapy scrapy&#xff1a;为爬取网站数据是&#xff0c;提取结构性数据而编写的应用框架 1. 安装 pip install scrapy 或者&#xff0c;国内源安装 pip install scrapy -i https&#xff1a;//pypi.douban.com/simple 2. 报错 报错1&#xff09;building ‘twisted.te…

Notepad++ 8.6.7 安装与配置全攻略(Windows平台)

一、软件定位与核心优势 Notepad 是开源免费的代码/文本编辑器&#xff0c;支持超过80种编程语言的高亮显示&#xff0c;相比系统自带记事本具有以下优势&#xff1a; 轻量高效&#xff1a;启动速度比同类软件快30%插件扩展&#xff1a;支持NppExec、JSON Viewer等200插件跨文…

建筑兔零基础自学python记录39|实战词云可视化项目——章节分布10(上)

这次我们来制作《红楼梦》各章节的分布情况&#xff1a; 源代码&#xff1a; import pandas as pd import numpy as np import matplotlib.pyplot as pltdf_hlm pd.read_csv("hlm.txt", names["hlm_texts"]).dropna()df_hlm df_hlm[~df_hlm.hlm_texts.s…

基于 ChatGPT 创建专属 GPTs

文章目录 基于 ChatGPT 创建专属 GPTs一、效果展示1.1 中文命名专家1.2 行程小助手 二、核心配置2.1 Instructions2.3 Actions 三、Agent 简介3.1 功能框架3.2 工作流程3.3 意图识别 四、数据流程 基于 ChatGPT 创建专属 GPTs ChatGPT 具备定制 GPTs 的能力&#xff0c;能够通…

【数据挖掘】异构图与同构图

在图论&#xff08;Graph Theory&#xff09;中&#xff0c;异构图&#xff08;Heterogeneous Graph&#xff09;和同构图&#xff08;Homogeneous Graph&#xff09;是两种不同的图结构概念&#xff0c;它们的主要区别在于节点和边的类型是否单一。 1. 异构图&#xff08;Hete…