博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
linux下文件描述符的查看及分析
阅读量:6482 次
发布时间:2019-06-23

本文共 2266 字,大约阅读时间需要 7 分钟。

起因

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

好吧。那就确定下原因。
在网上搜到有说lseek存在问题,“对于已经到达EOF的stream,使用lseek是不能让stream再次可读的”。具体参考。随即写了个命令行程序,在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总用量 0dr-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/22lrwx------ 1 root root 64  4月  1 15:48 1 -> /dev/pts/22lrwx------ 1 root root 64  4月  1 15:48 2 -> /dev/pts/22lr-x------ 1 root root 64  4月  1 15:48 3 -> /home/tocy/project/test.cpp

总结

了解下系统提供的文件操作接口还是不错的,以后遇到问题最起码知道去哪里跟踪。

主要参考:

  1. linux用户手册

转载地址:http://hrfuo.baihongyu.com/

你可能感兴趣的文章
WPF资料链接
查看>>
再次更新
查看>>
利用Windows自带的Certutil查看文件MD5
查看>>
开篇,博客的申请理由
查看>>
[JSOI2008]星球大战starwar BZOJ1015
查看>>
IntelliJ IDEA 注册码
查看>>
String字符串的截取
查看>>
Shell编程-环境变量配置文件
查看>>
Struts2和Spring MVC的区别
查看>>
git代码冲突
查看>>
git bash 风格调整
查看>>
HDOJ-1010 Tempter of the Bone
查看>>
日本开设无人机专业,打造无人机“人才市场”
查看>>
190行代码实现mvvm模式
查看>>
兼容几乎所有浏览器的透明背景效果
查看>>
Linux VNC server的安装及简单配置使用
查看>>
阿里宣布开源Weex ,亿级应用匠心打造跨平台移动开发工具
查看>>
Android项目——实现时间线程源码
查看>>
招商银行信用卡重要通知:消费提醒服务调整,300元以下消费不再逐笔发送短信...
查看>>
数据库运维体系_SZMSD
查看>>