linux下查看文件描述符,linux下文件描述符的查看及分析

起因

近期在调试一个Android播放内核是遇到上层传递的是fd(file descriptor),但是在文件播放结束之后调用lseek却提示返回-1,errno=29(#define ESPIPE 29 /* Illegal seek */)。

好吧。那就确定下原因。

在网上搜到有说lseek存在问题,“对于已经到达EOF的stream,使用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

#include

#include

#include

#include

#include

int main()

{

FILE * stream = fopen(__FILE__, "rb");

if (NULL == stream)

{

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)

{

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下文件描述符

http://blog.csdn.net/kumu_linux/article/details/7877770 文件描述符是一个简单的整数,用以标明每一个被进程所打开的文件和socket.第一个打开的 ...

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的理解

转自:http://www.cnblogs.com/Jezze/archive/2011/12/23/2299861.html 简单归纳:fd只是一个整数,在open时产生.起到一个索引的作用,进程通 ...

随机推荐

MySQL热备脚本

MYSQL 备份方法:    热备:    http://blog.itpub.net/27099995/viewspace-1295099/    http://blog.csdn.net/dban ...

MyEclipse SVN 插件

一.下载SVN插件subclipse 下载地址:http://subclipse.tigris.org/servlets/ProjectDocumentList?folderID=2240 在打开的网 ...

Knockout 是什么?

翻译:Knockout 轻松上手 - 1 Knockout 是什么? 原文名称:KnockoutJS Starter Knockout 是一个非常棒的脚本库,可是我发现许多人并不了解它,所以,思胜翻译 ...

Beta冲刺 第四天

Beta冲刺 第四天 1. 昨天的困难 1.网页使用了一些网上现成的模板,其主要是使用像素做处理的,所以检查起来比较费事费力. 2.使用github代码merge时出现了问题.所以花费了不少的时间在人 ...

寻找复杂背景下物体的轮廓(OpenCV / C++ - Filling holes)

一.问题提出 这是一个来自"answerOpenCV"(http://answers.opencv.org/question/200422/opencv-c-filling-hol ...

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();解码

你可能感兴趣的:(linux下查看文件描述符)