linux下查看⽂件描述符,linux下⽂件描述符的查看及分析
起因
近期在调试⼀个Android播放内核是遇到上层传递的是fd(file descriptor),但是在⽂件播放结束之后调⽤lseek却提⽰返回-
1,errno=29(#define ESPIPE 29 /* Illegal seek */)。
好吧。那就确定下原因。
在⽹上搜到有说lseek存在问题,“对于已经到达EOF的,使⽤lseek是不能让stream再次可读的”。具体参考Android NDK之fseek, lseek。随即写了个命令⾏程序,在android shell下验证了下,经过验证是可以的。那就继续吧。
最终发现⼀个有趣的现象,Android的MediaServer传递的fd只能在调⽤时使⽤,之后就被复⽤了,指针都改变了。具体发现的⽅法就是本⽂描述的内容。
⽂件操作
⽂件操作⽐较通⽤的就是C库的FILE(带缓冲的⽂件流),也就是常⽤的fopen, fclose, fprintf, fscanf, fseek, fread, fwrite等函数。这⾥⾯⽐较核⼼的概念是FILE结构,这是C库提供的跨平台的⽂件操作函数,多数情况下是封装了系统内核提供的⽂件读写函数,⽐如在windows下是CreateFile, CloseFile, OpenFile, WriteFile, ReadFile等函数,在linux下是open, close, lseek, read, write等内核API。
在linux下内核API主要提供了基于⽂件描述(FD,file descriptor)的⽂件操作机制,注意FD默认是⾮负的,通常0-stdin、1-stdout、2-stderr。
先看看如何实现FILE到fd的转换,函数fileno可以实现这种转换,原型如下:
int fileno(FILE *stream);
那么fd如何转换为FILE呢? 函数fdopen可以基于FD打开⽂件,原型如下:
FILE *fdopen(int fd, const char *mode);
那么如何通过fd拿到⽂件原始路径呢? 函数readlink提供了这种机制,可以参考下⾯代码
#include
#include
#include
linux重定向#include
#include
#include
#include
#include
int main()
{undefined
FILE * stream = fopen(__FILE__, "rb");
if (NULL == stream)
{undefined
printf("open %s failed\n", __FILE__);
return -1;
int fd = fileno(stream);
char buf[4096] = {0};
// read to file end
while (read(fd, buf, sizeof(buf)) > 0);
// test whether lseek is ok in EOF
off_t offset = lseek(fd, 0, SEEK_CUR);
printf("lseek ret %d err_no %d\n", offset, errno);
// read file path from fd
char path[PATH_MAX] = {0};
snprintf(path, sizeof(path), "/proc/%d/fd/%d", getpid(), fd);
memset(buf, 0, sizeof(buf));
int buf_size = readlink(path, buf, sizeof(buf));
if (buf_size < 0)
{undefined
printf("readlink() ret %d error %d\n", buf_size, errno);
}
else
printf("readlink() returned '%s' for '%s'\n", buf, path);
getchar();
if (NULL != stream)
fclose(stream);
return 0;
}
原理很简单,linux下的fd就是⼀个链接,可以通过/proc/pid/fd读取到相关信息。⽐如上⾯那个程序的输出如下:
/proc/11203/fd$ ll
总⽤量 0
dr-x------ 2 root root 0 4⽉ 1 15:48 ./
dr-xr-xr-x 9 root root 0 4⽉ 1 15:48 ../
lrwx------ 1 root root 64 4⽉ 1 15:48 0 -> /dev/pts/22
lrwx------ 1 root root 64 4⽉ 1 15:48 1 -> /dev/pts/22
lrwx------ 1 root root 64 4⽉ 1 15:48 2 -> /dev/pts/22
lr-x------ 1 root root 64 4⽉ 1 15:48 3 -> /home/tocy/project/test.cpp
了解下系统提供的⽂件操作接⼝还是不错的,以后遇到问题最起码知道去哪⾥跟踪。
主要参考:
Linux下
linux下⽂件描述符的介绍
当某个程序打开⽂件时,操作系统返回相应的⽂件描述符,程序为了处理该⽂件必须引⽤此描述符.所谓的⽂件描述符是⼀个低级的正整数.最前⾯的三个⽂件描述符(0,1,2)分别与标准输⼊(stdin),标准输出( ...
[ 总结 ] Linux 下⽂件描述符
1.概述: ⽂件描述符是内核为了⾼效管理已被打开的⽂件所创建的索引.是⼀个⾮负整数,⽤于代指被打开的⽂件.所有通过I/O操作的系统调⽤都通过⽂件描述符. ⽂件描述符⽤以表明每⼀个被进程所打开的⽂件和s ...
linux 最⼤⽂件描述符fd
使⽤四种框架分别实现百万websocket常连接的服务器 著名的 C10K 问题提出的时候, 正是 2001 年.这篇⽂章可以说是⾼性能服务器开发的⼀个标志性⽂档,它讨论的就是单机为1万个连接提供服务 ...
Linux Shell ⽂件描述符 及 stdin stdout stderr 重定向
Abstract: 1) Linux Shell 命令的标准输⼊.标准输出.标准错误,及其重定位: 2)Linux Shell 操作⾃定义⽂件描述符: ⽂件描述符是与⽂件相关联的⼀些整数,他们保持与已 ...
【详解】Linux的⽂件描述符fd与⽂件指针FILE*互相转换
使⽤系统调⽤的时候⽤⽂件描述符(file descriptor,简称fd)的时候⽐较多,但是操作⽐较原始.C库函数在I/O上提供了⼀些⽅便的包装(⽐如格式化I/O.重定向),但是对细节的控制不够. 如 ...
Linux的⽂件描述符
(1).⽂件描述符的定义 ⽂件描述符是内核为了⾼效管理已被打开的⽂件所创建的索引,⽤于指向被打开的⽂件,所有执⾏I/O操作的系统调⽤都通过⽂件描述符:⽂件描述符是⼀个简单的⾮负整数,⽤以表明每个被进程 ...
对于Linux中⽂件描述符的疑问以及解决
问题 每次web服务器或者是⼏乎所有Linux服务器都需要对⽂件描述符进⾏调整,我使⽤ulimit -n来查看当前⽤户的最多能打开的⽂件,默认设置的是1024个,但是系统运⾏起来以及开启⼀些简单的 ...
Linux中⽂件描述符fd和⽂件指针flip的理解
随机推荐
MySQL热备脚本
MyEclipse SVN 插件
Knockout 是什么?
翻译:Knockout 轻松上⼿ - 1 Knockout 是什么? 原⽂名称:KnockoutJS Starter Knockout 是⼀个⾮常棒的脚本库,可是我发现许多⼈并不了解它,所以,思胜翻译 ...
Beta冲刺 第四天
Beta冲刺 第四天 1. 昨天的困难 1.⽹页使⽤了⼀些⽹上现成的模板,其主要是使⽤像素做处理的,所以检查起来⽐较费事费⼒. 2.使⽤github 代码merge时出现了问题.所以花费了不少的时间在⼈ ...
寻复杂背景下物体的轮廓(OpenCV / C++ - Filling holes)
Flashbuilder的bug FlashBuilder 1119: 访问可能未定义的属性 on (通过 static 类型
FlashBuilder 1119: 访问可能未定义的属性 on (通过 static 类型 当此问题出现的时候 ⽆论 刷新 清理 注释 删除 乃⾄重启电脑都⽆济于
appium多机并⾏测试
在实际应⽤中需要对多个机型并⾏测试,节省时间 多机测试的思路 启动多个appium server与多台机器交互(android和ios均可) 注意:⼀定要使⽤node安装appium的命令⾏,使⽤ ...
Android Studio关于USB device not found的解决的⽅法
Android Studio关于USB device not found的解决的⽅法 我们使⽤Android Studio进⾏Android开发时.当我们使⽤真机进⾏调试时.⾮常可能会出现USB de ...
HBase & thrift & C++编程
⽬录 ⽬录 1 1. 前⾔ 1 2. 启动和停⽌thrift2 1 2.1. 启动thrift2 1 2.2. 停⽌thrift2 1 2.3. 启动参数 2 3. hbase.thrift 2 3. ...
对特殊字符编码js与c#中的处理⽅法
js: encodeURIComponent();编码 c#: Uri.UnescapeDataString();解码
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论