当前位置: 首页 > article >正文

【Linux】Linux 操作系统 - 18 , 重谈文件(二) ~ 文件描述符和重定向原理 , 手把手带你彻底理解 !!!

文章目录

  • 文件描述符
    • 一 、Linux 系统对文件的管理(要知道)
    • 二 、什么是文件描述符 fd ?
    • 三 、再探文件被管理过程(重要)
    • 四 、文件描述符 0 、1、2
      • 1. 文件描述符的分配原则
      • 2. 提前认识三个默认打开的文件
  • 重定向原理(重要)
    • 一 、重定向现象
    • 二 、深入剖析重定向现象(重要)
      • 1 . 重定向的本质是什么 ???
      • 2 . 各种重定向实现原理
        • 2.1 dup2 系统调用(理解 , 掌握)
        • 2.2 输出重定向
        • 2.3 输入重定向
        • 2.4 追加重定向
      • 3 . 重定向的原理(面试考)
  • 正式谈三个默认打开的文件
    • 一 、stderr
    • 二 、重定向的使用(重要)(重点讲解标准错误)
      • 1 . 重定向的完整写法
      • 2 . 将错误信息和正常信息隔离(重要)
      • 3 . 将错误信息和正常信息打印在一起
  • 总结


文件描述符


  篇章一中笔者提到了文件描述符的概念 , 本节就详细对其进行介绍 !

  对以下系统调用中会涉及文件描述符的概念 :

write(int fd, ....) - write to a file descriptor - 文件描述符read( int fd, .... ) - read from a file descriptor - 文件描述符 close(int fd) - close a file descriptor  - 文件描述符 

一 、Linux 系统对文件的管理(要知道)


  之前第一篇章提到操作文件 , 就是进程操作文件 ! 那么考虑一个问题 ???
  在系统中一切皆文件 , 那么文件多了 , 要不要被管理呢 ???

答 : 文件要被管理 ! 那怎么管理呢 ??? 先描述 , 再组织 !
  既然要描述 , 那么就会有数据结构吧 !

以下便是具体描述 :

在这里插入图片描述


二 、什么是文件描述符 fd ?


  上面也提到了文件被管理是通过文件描述符表管理的 , 那这个文件描述符表是个什么呢 ???

  • 文件描述符表是一个数组 !
  • 文件描述符的本质就是数组的下标 ! , 即 : fd 的本质就是数组的下标 !
  • flies_struct 这个数据结构中包含一个结构体指针数组 , 这个数组就是文件描述符表 !
  • 内核源代码中的 files_struct
struct files_struct {
....
....
....
....
....
....//其中包含一个结构体指针数组
struct file __rcu * fd_array[NR_OPEN_DEFAULT];  // 文件描述符表 
};

在这里插入图片描述

  • 每打开一个文件 , 就会有一个文件描述符来描述该文件 , 即 : 就会有一个指针指向该文件 !

在这里插入图片描述


三 、再探文件被管理过程(重要)

在这里插入图片描述


  总结文件被管理的过程(面试可能考) :

在这里插入图片描述
记住一个图 :
在这里插入图片描述


  所以 , 还可以得出一个结论 :

对文件内容的任何操作 , 必须先把文件的内容加载到内核对应的文件缓冲区内 , 避免频繁 I/O , 提高效率 !


四 、文件描述符 0 、1、2


  有了以上的理解 , 现在便好介绍 0 , 1 , 2 了 .

  笔者之前提过 , 系统会为每个文件分配一个文件描述符 , 每一个描述符对应一个文件 !

1. 文件描述符的分配原则


  因为文件描述符是数组的下标 , 所以会有以下原则 :

  • 找到 files_struct 数组中没有被使用的最小的下标 , 作为当前文件的描述符 ! 注意 : 是最小的下标 !!!
/ fd 分配原则#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>int main()
{//close(0);//int fd = open("log.txt" , O_CREAT | O_WRONLY | O_TRUNC , 0666);	//printf("fd : %d\n",fd);   **********  打印 0//close(2);//int fd = open("log.txt" , O_CREAT | O_WRONLY | O_TRUNC , 0666);	//printf("fd : %d\n",fd);   **********  打印 2int fd = open("log.txt" , O_CREAT | O_WRONLY | O_TRUNC , 0666);	printf("fd : %d\n",fd);    **********  打印 3return 0;
}

2. 提前认识三个默认打开的文件


  之前笔者也讲过 , 系统会自动打开三个默认文件 !

  这三个默认文件 , 分别对应 :

  • 键盘 --- 文件描述符 0
  • 显示器 --- 文件描述符 1
  • 显示器 --- 文件描述符 2

观察一个现象

#include <stdio.h>
#include <unistd.h>int main()
{	printf("进入第一次输入 :\n");int a = 0;scanf("%d",&a);printf("%d\n",a);close(0);printf("进入第二次输入 :\n");int b = 10;scanf("%d",&b);printf("%d\n",b);return 0;
}

在这里插入图片描述

所以 , 上面完全可以印证文件描述符 0 对应的就是键盘文件(C语言 — stdin ) !


  其余 , 学者可以自行验证 !


重定向原理(重要)


  我们之前经常用 > , 这个就是重定向 , 那么其原理真的了解吗 ?

  重定向分类 :

  • 输出重定向
  • 输入重定向
  • 追加重定向

一 、重定向现象


  给出以下代码 : 你会发现什么现象 ??

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>int main()
{	// 演示输出重定向现象 , 即 1 -- 对于 stdout// 关闭 1 对于的文件 , 即 : 关闭显示器文件close(1);int fd = open("redir.txt" , O_CREAT|O_WRONLY | O_APPEND , 0666);//打印 , 默认打印到显示器 , 即 : 只会向 1 设备文件中打印 ; 但当关闭 stdout 文件后 , 会打印到 redir.txt 中 printf("I am file , defalut printf to stdout\n");return 0;
}*************** 关闭 1 , 不会在显示器上打印了 , 而是打印在了 redir.txt 中 **************

二 、深入剖析重定向现象(重要)


  对以上的现象 , 为什么关闭了 1 对应的文件 , 不会打印在显示器 , 却打印到了其它文件了呢 ??

在这里插入图片描述

在这里插入图片描述

1 . 重定向的本质是什么 ???


  通过以上讲解的 , 现象的剖析 , 便可得到 :

重定向的本质 : 改变文件描述符的指针指向 !!!!


2 . 各种重定向实现原理

2.1 dup2 系统调用(理解 , 掌握)


  这里介绍一个系统调用 :

 dup, dup2, dup3 - duplicate a file descriptor , 复制一个文件描述符int dup2(int oldfd, int newfd);描述 : 使用新的 newfd 这个文件描述符 , 形成 oldfd 这个文件描述符的拷贝 !简单理解 : 它会将 oldfd 所指向的文件复制到 newfd,新的会指向旧的内容 !

在这里插入图片描述


2.2 输出重定向
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>// ls > xxx , 往 xxx 写入
int main()
{int fd = open("dir.txt" , O_CREAT | O_WRONLY | O_TRUNC , 0666);// old , new , 新的指向旧的 dup2(fd , 1); // 1 本身指向的是显示器文件 , 在 C语言中为 : stdout , 现在指向 fd printf("Hello newfile\n");const char* str = "dir success!\n";write(1 , str , strlen(str));close(fd); return 0;
}

在这里插入图片描述

  通过我们手动编写的原理 , 这里就可以知道为什么 > 符号可以用来新建文件了 . 因为 open 文件时会 O_CREAT , 文件不存在 , 就创建 !


2.3 输入重定向
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>// ls < xxx , 从 xxx 读取内容
int main()
{int fd = open("dir.txt" , O_RDONLY);dup2(fd , 0); // 0 原来指向键盘文件 , 默认从键盘上读取内容, 现在指向 dir.txt char buff[200];memset(buff , 0 , sizeof(buff));//读 fd 文件	while(1)	{	// 从 0 指向的设备文件中读 ssize_t red = read(0 , buff , sizeof(buff)-1);	// 不读 \0 l if(red > 0){buff[red] = 0;printf("%s\n",buff);	}		if(red == 0 ){break;}}return 0;
}


  以上就做到了 , 本来是从键盘读取 , 现在是在新的文件中读取 !


2.4 追加重定向


  这里实现一个追加输出重定向 .

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>/ 追加输出重定向
// ls >> xxx , 往 xxx 写入
int main()
{int fd = open("dir.txt" , O_CREAT | O_WRONLY | O_APPEND , 0666);// old , new , 新的指向旧的 dup2(fd , 1); // 1 本身指向的是显示器文件 , 在 C语言中为 : stdout , 现在指向 fd printf("Hello newfile\n");const char* str = "dir success!\n";write(1 , str , strlen(str));close(fd); return 0;
}


  这里就可以发现 , 可以追加写入到 dir.txt 这个文件中了 !


3 . 重定向的原理(面试考)


  通过以上各个重定向的编写 , 我们可以发现一个共同点 , 那就是每个重定向都是 : 打开方式 + dup2 来进行的 !

面试总结 :
在这里插入图片描述


正式谈三个默认打开的文件


  在之前的篇章笔者一直在铺垫三个默认打开的文件 , 但是没有正式讲解 , 这里便给出 !

在这里插入图片描述

  通过文件描述符的学习 , 我们这里就可以知道了 , 以下 :

  • 键盘文件对应文件描述符 0
  • 显示器文件(stdout) 对应文件描述符 1
  • 显示器文件(stderr) 对应文件描述符 2


  所以 , 默认情况下 , 0 , 1 , 2 是被占用的 , 我们之后打开的文件默认是从文件描述符 3 开始的 !


  那对于 stderr 这个显示器文件一直没有介绍 , 以下对其详细解释 !

一 、stderr


  stderr 是显示器文件 , 那么和 stdout 的显示器文件到底有什么区别呢 ??

  • stdout 是显示器文件 , 一般显示我们正常的程序信息 .
  • stderr 是显示器文件 , 一般显示我们错误的程序信息 .
  • 二者本质都是指向同一个硬件 , 但是二者所对应的文件描述符不同 !

描述符不同 , 目的是让我们用重定向进行正常信息和错误信息的隔离 !!!


二 、重定向的使用(重要)(重点讲解标准错误)

1 . 重定向的完整写法

假如这里需要把可执行程序 a.out 里面的内容重定向到文件 log.txt 中 . 我们平时写的 x > log.txt 的完整写法是 :a.out 1 > log.txt // 解释
意思就是 : 把 a.out 里面的 1 文件描述符对应的内容重定向到 log.txt 中 .


  这里看一段代码理解 :

#include <iostream>
#include <cstdio>int main()
{	//输出 , 默认是在显示器输出 , 1 对应的文件 ,stdout(C语言) , cout(C++)printf("Hello C!\n");std::cout << "Hello C++!" << std::endl;//输出错误信息 , 默认也是在显示器输出 , 1 对应文件 ,stderr , cerrconst char* str = "Hello C err!\n";fprintf(stderr , "%s" , str);std::cerr << "Hello C++ Err!" << std::endl;return 0;
}
  • 编译后执行 , 不进行重定向 !

在这里插入图片描述

  • 编译后执行 , 进行重定向 ! (不用完整写法)
    在这里插入图片描述

  • 编译后执行 , 进行重定向 ! (用完整写法)
    在这里插入图片描述


  所以 , 重定向时 , 可以指定文件描述符 , 这是最完整的写法 !!!


2 . 将错误信息和正常信息隔离(重要)


  重定向完整写法的最大应用就是将二者进行隔离 , 这样方便程序员去查看错误信息 !

./mydir 1>log.normal  2>log.err

在这里插入图片描述

  所以 , 要清楚

  • 文件描述符 1 - > 对应的是显示器文件 , stdout / cout , 即 : 一般打印我们程序程序信息 !
  • 文件描述符 2 - > 对于的是显示器文件 , stderr / cerr , 即 : 一般打印我们程序的错误信息 !
  • 通过 重定向 可以将不同的信息打印到不同文件 ! 这是常做的 !!!!

3 . 将错误信息和正常信息打印在一起


  当我们需要将二者信息同时都重定向到一个文件该怎么做 ???
  可能有的人会这样做 :

.mydir  1>log.normal  2>log.normal  // 这个有问题吗 ????????

  上面的做法是有问题的 , 因为 > 底层是用的系统调用 open 呀 , open 的打开文件方式是用了 O_TRUNC 的 , 也就意味着会先清空在写入 , 所以 , 非常错误 !!!

  • 正确做法
./mydir 1>log.normal 2>&1 


2 > &1 的意思就是 : 再把 2 里面的内容添加到 1 里面 , 不清空 !

在这里插入图片描述

总结

在这里插入图片描述

相关文章:

【Linux】Linux 操作系统 - 18 , 重谈文件(二) ~ 文件描述符和重定向原理 , 手把手带你彻底理解 !!!

文章目录 ● 文件描述符一 、Linux 系统对文件的管理(要知道)二 、什么是文件描述符 fd ?三 、再探文件被管理过程(重要)四 、文件描述符 0 、1、21. 文件描述符的分配原则2. 提前认识三个默认打开的文件 ● 重定向原理(重要)一 、重定向现象二 、深入剖析重定向现象(重要)1…...

第五十三节:综合项目实践-车牌识别系统

一、项目背景与意义 车牌识别系统(LPR)是智能交通领域的核心技术之一,广泛应用于停车场管理、违章抓拍、高速公路收费等场景。本文将通过Python+OpenCV实现一个完整的车牌识别系统,涵盖图像预处理→车牌定位→字符分割→字符识别四大核心环节。 二、系统架构设计 技术栈组…...

AI时代新词-AI伦理(AI Ethics)

一、什么是AI伦理&#xff1f; AI伦理&#xff08;AI Ethics&#xff09;是指在人工智能&#xff08;AI&#xff09;的设计、开发、部署和使用过程中&#xff0c;涉及的道德、法律和社会问题的综合考量。它关注AI技术对人类社会、文化、价值观以及个人权利的影响&#xff0c;并…...

湖北理元理律师事务所债务优化服务中的“四维平衡“之道

债务问题解决需要兼顾多方利益&#xff0c;湖北理元理律师事务所通过独特的服务模式&#xff0c;在法律、经济、心理、社会四个维度建立平衡点。 一、法律维度的专业把控 合规性审查&#xff1a; 合同效力认定 诉讼时效核查 担保责任界定 程序合法性&#xff1a; 所有协…...

Git Push 失败:HTTP 413 Request Entity Too Large

Git Push 失败&#xff1a;HTTP 413 Request Entity Too Large 问题排查 在使用 Git 推送包含较大编译产物的项目时&#xff0c;你是否遇到过 HTTP 413 Request Entity Too Large 错误&#xff1f;这通常并不是 Git 的问题&#xff0c;而是 Web 服务器&#xff08;如 Nginx&am…...

第10章 网络与信息安全基础知识

网络概述 多模光纤的特点&#xff1a;成本低&#xff0c;宽芯线&#xff0c;聚光好&#xff0c;耗散大&#xff0c;低效&#xff0c;用于低速度、短距离的通信。 单模光纤的特点&#xff1a;成本高&#xff0c;窄芯线&#xff0c;需要激光源&#xff0c;耗散小&#xff0c;高效…...

GO语言学习(九)

GO语言学习&#xff08;九&#xff09; 上一期我们了解了实现web的工作中极为重要的net/http抱的细节讲解&#xff0c;大家学会了实现web开发的一些底层基础知识&#xff0c;在这一期我来为大家讲解一下web工作的一个重要方法&#xff0c;&#xff1a;使用数据库&#xff0c;现…...

go 访问 sftp 服务 github.com/pkg/sftp 的使用踩坑,连接未关闭(含 sftp 服务测试环境搭建)

前言 最近在使用 sftp 服务时&#xff0c;被告知发起了海量的连接&#xff0c;直接把服务器搞崩&#xff0c;ip 被封了。 这是啥情况&#xff1f; golang 写的代码&#xff0c;我就正常的访问 sftp 服务&#xff0c;连接使用过后也都关闭了&#xff0c;咋会出现连接一直连着…...

Linux多线程(二)之进程vs线程

文章目录 Linux进程VS线程进程和线程进程的多个线程共享关于进程线程的问题 重谈地址空间Linux线程周边的概念 Linux进程VS线程 进程和线程 进程是资源分配的基本单位&#xff08;进程是承担分配系统资源的基本实体&#xff09; 执行流也是资源&#xff01;线程是进程内部的执…...

【MogDB】测试 ubuntu server 22.04 LTS 安装mogdb 5.0.11

测试 ubuntu server 22.04 LTS 安装mogdb 5.0.11 使用的操作系统镜像是 https://releases.ubuntu.com/22.04/ubuntu-22.04.5-live-server-amd64.iso 装好操作系统后&#xff0c;把root登录打开了&#xff0c;方便后续操作。 测试过程 使用官方命令在线安装ptk rootubuntu22…...

AI时代新词-数字孪生(Digital Twin)

一、什么是数字孪生&#xff08;Digital Twin&#xff09;&#xff1f; 数字孪生&#xff08;Digital Twin&#xff09;是一种通过创建物理实体的虚拟副本&#xff0c;并利用数据和算法来模拟、分析和优化物理实体的性能和行为的技术。数字孪生结合了物联网&#xff08;IoT&am…...

【HW系列】—web常规漏洞(文件上传漏洞)

文章目录 一、简介二、危害三、文件检测方式分类四、判断文件检测方式五、文件上传绕过技术六、漏洞防御措施 一、简介 文件上传漏洞是指Web应用程序在处理用户上传文件时&#xff0c;未对文件类型、内容、路径等进行严格校验和限制&#xff0c;导致攻击者可上传恶意文件&…...

如何实现 C/C++ 与 Python 的通信

C/C 与 Python 的通信可以通过多种方式实现&#xff0c;如使用 C API、Ctypes、Cython、SWIG、Python.h 或基于共享库的调用等。其中&#xff0c;使用 Ctypes 方式最为简便&#xff0c;适合快速调用已有的 C 函数库。例如&#xff0c;通过将 C 代码编译为动态链接库&#xff08…...

python炸鱼船

import pygame, random # 加载库 from pygame.locals import * pygame.init() pygame.display.set_caption("炸渔船") canvas pygame.display.set_mode((700, 500)) bgpygame.image.load("bg.png") bgpygame.transform.scale(bg,(700,500))class Hero(py…...

使用AutoKeras2.0的AutoModel进行结构化数据回归预测

1、First of All: Read The Fucking Source Code import autokeras as ak import numpy as np from sklearn.model_selection import train_test_split from sklearn.metrics import mean_squared_error# 生成数据集 np.random.seed(42) x np.random.rand(1000, 10) # 生成1…...

好用但不常用的Git配置

参考文章 文章目录 tag标签分支新仓库默认分支推送 代码合并冲突处理默认diff算法 tag标签 默认是以字母顺序排序&#xff0c;这会导致一些问题&#xff0c;比如0.5.101排在0.5.1000之后。为了解决这个问题&#xff0c;我们可以把默认排序改为数值排序 git config --global t…...

ULVAC VWR-400M/ERH 真空蒸发器 Compact Vacuum Evaporator DEPOX (VWR-400M/ERH)

ULVAC VWR-400M/ERH 真空蒸发器 Compact Vacuum Evaporator DEPOX (VWR-400M/ERH)...

P1068 [NOIP 2009 普及组] 分数线划定

题目描述 世博会志愿者的选拔工作正在 A 市如火如荼的进行。为了选拔最合适的人才&#xff0c;A 市对所有报名的选手进行了笔试&#xff0c;笔试分数达到面试分数线的选手方可进入面试。面试分数线根据计划录取人数的 150% 划定&#xff0c;即如果计划录取 m 名志愿者&#xf…...

PPT连同备注页(演讲者模式)一块转为PDF

首先&#xff0c;进入创建PDF/XPS&#xff1a; 然后进入选项&#xff1a; 发布选项-发布内容里选备注页&#xff1a; 导出的原始结果是这样的&#xff1a; 这个时候裁剪一下&#xff0c;范围为所有页面&#xff1a; 最终结果&#xff1a; 如果导出不选“备注页”而是只勾选“包…...

第三十二天打卡

作业&#xff1a;参考pdpbox官方文档中的其他类&#xff0c;绘制相应的图&#xff0c;任选即可 1. 安装并导入库 确保安装与文档版本一致的 pdpbox&#xff08;此处以 0.3.0 为例&#xff09;&#xff1a; bash 复制 下载 pip install pdpbox0.3.0 导入所需库&#xff1a…...

项目三 - 任务8:实现词频统计功能

本项目旨在实现一个词频统计功能&#xff0c;通过读取文本文件并利用Java编程技巧处理和分析文本数据。首先&#xff0c;使用BufferedReader逐行读取文件内容&#xff0c;然后通过String.split(" ")方法将每行文本分割成单词数组。接下来&#xff0c;采用HashMap来存…...

MongoDB 快速整合 SpringBoot 示例

1.添加依赖<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spr…...

2025.05.22-得物春招机考真题解析-第二题

&#x1f4cc; 点击直达笔试专栏 &#x1f449;《大厂笔试突围》 &#x1f4bb; 春秋招笔试突围在线OJ &#x1f449; 笔试突围OJ 02. 魔法书页重排 问题描述 A先生是一位魔法师&#xff0c;他有一本古老的魔法书&#xff0c;书中有 n n n 页&#xff0c;每页都刻有一个魔…...

ollama list模型列表获取 接口代码

ollama list模型列表获取 接口代码 curl http://localhost:11434/v1/modelscoding package hcx.ollama;/*** ClassName DockerOllamaList* Description TODO* Author dell* Date 2025/5/26 11:31* Version 1.0**/import java.io.BufferedReader; import java.io.InputStreamR…...

OPC Client第5讲(wxwidgets):初始界面的事件处理;按照配置文件初始化界面的内容

接上一讲&#xff0c;即实现下述界面的事件处理代码&#xff1b;并且按照配置文件初始化界面的内容&#xff08;三、&#xff09; 事件处理的基础知识&#xff0c;见下述链接五、 OPC Client第3讲&#xff08;wxwidgets&#xff09;&#xff1a;wxFormBuilder&#xff1b;基础…...

什么是BFC,如何触发BFC,BFC有什么特性?

理解 BFC指的是块级格式化上下文,处于BFC内部的盒子与外界互不影响 触发条件 position:absolute/fixed都会产生bfcdisplay:inline-block,table,flex等float:left/right 浮动也会产生bfchtml根元素也是bfc bfc的特性 属于同一个BFC下的盒子会垂直排列属于同一个BFC下的两个…...

python做题日记(9)

第二十一题 第二十一题是合并两个有序链表&#xff0c;合并后的链表仍然需要保持有序&#xff0c;因为在合并之前已经是两个有序链表&#xff0c;因此在合并时只需要遍历比较两个链表中的下一结点数值&#xff0c;将其中较小的一个结点添加到新的列表中。如果有任何一个链表已经…...

Leetcode 3557. Find Maximum Number of Non Intersecting Substrings

Leetcode 3557. Find Maximum Number of Non Intersecting Substrings 1. 解题思路2. 代码实现 题目链接&#xff1a;3557. Find Maximum Number of Non Intersecting Substrings 1. 解题思路 这一题就是一个比较直接的动态规划的题目&#xff0c;我们只需要考察每一个位是否…...

【C++进阶篇】初识哈希

哈希表深度剖析&#xff1a;原理、冲突解决与C容器实战 一. 哈希1.1 哈希概念1.2 哈希思想1.3 常见的哈希函数1.3.1 直接定址法1.3.2 除留余数法1.3.3 乘法散列法&#xff08;了解&#xff09;1.3.4 平方取中法&#xff08;了解&#xff09; 1.4 哈希冲突1.4.1 冲突原因1.4.2 解…...

Spring Boot——自动配置

目录 1.bean加载方式 1.1XML方式声明bean 1.2 xml 注解方式声明bean 1.3通过Configuration和Bean 1.4使用Import注解 1.5使用上下文对象在容器初始化完毕后注入bean 1.6使用ImportSelector接口 1.7实现ImportBeanDefinitionRegistrar接口 1.8bean加载方式&#xff08;…...