dirent中哈大高铁为什么是d没有d_type

现在位置:
来自外部的引用: 1 条
Linux学习:dirent.h — 获取某文件夹目录内容 – FIGHTING
2012年五月
14151617181920
21222324252627Linux下DIR,dirent,stat等结构体详解
Linux下DIR,dirent,stat等结构体详解
copy from&
最近在看Linux下文件操作相关章节,遇到了这么几个结构体,被搞的晕乎乎的,今日有空,仔细研究了一下,受益匪浅。
首先说说DIR这一结构体,以下为DIR结构体的定义:
struct&__dirstream
&&&&void&*__&
&&&&char&*__&
&&&&int&__entry_&
&&&&char&*__&
&&&&int&__entry_&
&&&&size_t&__&
&&&&size_t&__&
&&&&__libc_lock_define&(,&__lock)&
typedef&struct&__dirstream&DIR;&&
DIR结构体类似于FILE,是一个内部结构,以下几个函数用这个内部结构保存当前正在被读取的目录的有关信息(摘自)。函数 DIR *opendir(const char *pathname),即打开文件目录,返回的就是指向DIR结构体的指针,而该指针由以下几个函数使用:
struct&dirent&*readdir(DIR&*dp);
void&rewinddir(DIR&*dp);
int&closedir(DIR&*dp);
long&telldir(DIR&*dp);
void&seekdir(DIR&*dp,long&loc);&&
关于DIR结构,我们知道这么多就可以了,没必要去再去研究他的结构成员。
接着是dirent结构体,首先我们要弄清楚目录文件(directory file)的概念:这种文件包含了其他文件的名字以及指向与这些文件有关的信息的指针(摘自)。从定义能够看出,dirent不仅仅指向目录,还指向目录中的具体文件,readdir函数同样也读取目录下的文件,这就是证据。以下为dirent结构体的定义:
struct&dirent
  long&d_&&&
&&&&off_t&d_&&&
&&&&unsigned&short&d_&&&
&&&&unsigned&char&d_&&&
&&&&char&d_name&[NAME_MAX+1];&&&
从上述定义也能够看出来,dirent结构体存储的关于文件的信息很少,所以dirent同样也是起着一个索引的作用,如果想获得类似ls -l那种效果的文件信息,必须要靠stat函数了。
通过readdir函数读取到的文件名存储在结构体dirent的d_name成员中,而函数
int stat(const char *file_name, struct stat *buf);
的作用就是获取文件名为d_name的文件的详细信息,存储在stat结构体中。以下为stat结构体的定义:
struct&stat&{
&&&&&&&&mode_t&&&&&st_&&&&&&&&&
&&&&&&&&ino_t&&&&&&st_&&&&&&&&&
&&&&&&&&dev_t&&&&&&st_&&&&&&&&&&
&&&&&&&&dev_t&&&&&&st_&&&&&&&&&
&&&&&&&&nlink_t&&&&st_&&&&&&&&
&&&&&&&&uid_t&&&&&&st_&&&&&&&&&&
&&&&&&&&gid_t&&&&&&st_&&&&&&&&&&
&&&&&&&&off_t&&&&&&st_&&&&&&&&&
&&&&&&&&time_t&&&&&st_&&&&&&&&
&&&&&&&&time_t&&&&&st_&&&&&&&&
&&&&&&&&time_t&&&&&st_&&&&&&&&
&&&&&&&&blksize_t&st_&&&&&&
&&&&&&&&blkcnt_t&&&st_&&&&&&&
&&&&&&};&&
这个记录的信息就很详细了吧,呵呵。
最后,总结一下,想要获取某目录下(比如a目下)b文件的详细信息,我们应该怎样做?
首先,我们使用opendir函数打开目录a,返回指向目录a的DIR结构体c。
接着,我们调用readdir( c)函数读取目录a下所有文件(包括目录),返回指向目录a下所有文件的dirent结构体d。
然后,我们遍历d,调用stat(d-&name,stat *e)来获取每个文件的详细信息,存储在stat结构体e中。
总体就是这样一种逐步细化的过程,在这一过程中,三种结构体扮演着不同的角色。
---------------------------------------------------------------------华丽丽的分割线---------------------------------------------------------------------------------------------------------------------------------------------
& &首先,关于上文提到的“DIR结构体类似于FILE,是一个内部结构”此句中的内部结构不是很明白,后来看到一遍博文有介绍FILE结构,具体如下:
博文地址:
“struct file结构体定义在include/linux/fs.h中定义。文件结构体代表一个打开的文件,系统中的每个打开的文件在内核空间都有一个关联的 struct file。它由内核在打开文件时创建,并传递给在文件上进行操作的任何函数。在文件的所有实例都关闭后,内核释放这个数据结构。在内核创建和驱动源码中,struct
file的指针通常被命名为file或filp。”
此处说FILE结构是在内核打开文件时创建的。参考以前的关于FILE操作的代码可以发现,我们在使用FILE结构时是直接声明一个FILE结构的指针,例如:
然后使用fopen函数返回一个FILE结构指针给fp。我们并没有声明一个结构体,而只是声明该结构体的指针。
所以本人猜测,具体的结构体的内存分配已经由内核帮我们完成了。
DIR结构的使用方法和FILE类似,在《Linux程序设计第四版》的P104有一个打印目录下所有文件及目录的程序,代码如下:
#include &unistd.h&
#include &stdio.h&
#include &dirent.h&
#include &string.h&
#include &sys/stat.h&
#include &stdlib.h&
void printdir(char *dir, int depth)
struct dirent *
if ((dp = opendir(dir)) == NULL) {
fprintf(stderr, &Can`t open directory %s\n&, dir);
chdir(dir);
while ((entry = readdir(dp)) != NULL) {
lstat(entry-&d_name, &statbuf);
if (S_ISDIR(statbuf.st_mode)) {
if (strcmp(entry-&d_name, &.&) == 0 ||
strcmp(entry-&d_name, &..&) == 0 )
printf(&%*s%s/\n&, depth, &&, entry-&d_name);
printdir(entry-&d_name, depth+4);
printf(&%*s%s\n&, depth, &&, entry-&d_name);
chdir(&..&);
closedir(dp);
int main(int argc, char *argv[])
char *topdir = &.&;
if (argc &= 2)
topdir = argv[1];
printf(&Directory scan of %s\n&, topdir);
printdir(topdir, 0);
printf(&done.\n&);
在这个程序中我们使用的DIR结构也只是声明了该结构的指针,那么DIR结构应该也是同FILE结构一样,在打开一个目录的时候,由内核帮我们分配该结构体的内存。
dirent结构也是如此。但stat结构却是要我们自己声明结构体的。
我的热门文章
即使是一小步也想与你分享在学习linux中posix api时,遇到了一个目录文件下面一条目录信息的结构体
struct dirent
_kernel_off_t d_
unsigned short d_
unsigned char
//在有些系统中是没有这个成员的,比如本人使用的centos 6
char d_name[256];
&  我不明白这个地方的d_reclen是什么东东,在网上查了一下,有人说是strlen(d_name),实际上是不对的。严格的说,这个成员是这个结构体除了d_name以外的成员+d_name中实际所占的char个数组成的结构体的长度!所以常见的值有16,20,24等等。这个会在最后解释。这就涉及到结构体成员在内存中分配的方式。记得以前专门研究过这个,但是没有整理,现在忘了一些细节。为了搞清楚这个问题,我又重新的查看了一遍网上关于结构体内存分配的一些说法,发现还是是错误百出!为了方便自己查询,于是写了这个扎记。
  首先要说的几点是关于概念性的东西,现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始。但是,计算机在存储数据的时候,为了访问效率的考虑,在访问特定变量的时候经常在特定的内存访问,这就需要各类型数据按照一定的规则在空间上排列,而不是顺序的一个接一个的排放,这就是对齐。(参考百度百科)
  如果一个变量的内存地址正好位于它长度的整数倍,他就被称做自然对齐。如果机器的整型值长度为4个字节,假设一个整型变量的地址为0x,那它就是自然对齐的。假设上面整型变量的地址不是自然对齐,比如为0x,则CPU如果取它的值的话需要 访问两次内存,第一次取从0xx的两个字节,第二次取从0xx的两个字节。t然后组合得到所要的数据。如果变量在0x地址上的话则要访问三次内存,第一次为一个字节,第二次为两个字节,第三次为一个字节,然后组合得到整型数据。而如果变量在自然对齐位置上,则只要一次就可以取出数据。一些系统对对齐要求非常严格,比如sparc系统,如果取未对 齐的数据会发生错误,举个例:     char ch[4];  char *p = &ch[1];  //这个地方取第一个的原因是保证第二个元素的地址肯定不是4的倍数。  int i = *(int *)p;  运行时会报segment error,而在x86上就不会出现错误,只是效率下降。(参考一篇网文)
  那么实际在考虑到程序编写过程中的对齐,还需要引出一个重要的概念:对齐参数。对于不同的系统,默认的对齐参数是不一样的,Win32平台下的微软VC编译器在默认情况下采用如下基本数据类型T的大小,即sizeof(T)。Linux下的GCC奉行的是另外一套规则:任何2字节大小(包括单字节)的数据类型(比如short)的对齐参数就是sizeof(T),而其它所有超过2字节的数据类型(比如long,double)都以4为对齐模数。了解了对齐参数之后,我们对齐的规则是:每个成员按其类型的大小和指定对齐参数(这里默认是8字节)中较小的一个对齐。并且结构的总长度必须为所用过的所有对齐参数的整数倍,不够就补空字节。
文中所有例子都使用gcc编译,版本为gcc version 4.4.6
(Red Hat 4.4.6-4) (GCC) 。默认的对齐参数在前文已经提到,不再赘述。
[pengliang@www ]$ ./structlengthsizeof(int):4
sizeof(long):4sizeof(char):1sizeof(short):2sizeof(double):8
结构体内存分配例子一:
1 struct test1
测试可知,
sizeof(struct test1)=12;
&offsetof(struct test1,a)=0;
offsetof(struct test1,b)=4;
offsetof(struct test1,c)=8;  注:offsetof是用来判断一个成员在内存中分配的位置距离整个结构体开始位置的偏移量
结构体第一个成员为char类型,它的对齐参数为:1,它可以放到任何位置(任何数都可以是1的整数倍),占用一个字节。
b是整型,它的对齐参数是4,所以它需要放到4的整数倍的位置。因为起始的地方肯定是可以被4整除的,所以最近的一个4的整数是a的地址+4,所以需要在a后填充3个空白字节,然后放b。
c同a,占用一个字节。所以这个结构体目前所占的长度为:1+3+4+1=9。根据前面的说法,结构体的总长度必须为使用过的所以的对齐参数的整数倍,其实就是max(所有的对齐参数),在本例子中就是4,那么这个结构体的总长度必须为4的整数倍,9最近的就是12,所以在c后面补充3个空白字符!!!这个结构体的实际利用率只有50%。
是不是很简单呢?在网上很多帖子中,有人说结构体的总长度必须是结构体中所有类型的最长大小的整数倍。其实在gcc这就是不对的,自己思考为什么。想想这个例子
struct t{&&&&&}在gcc环境下是12&& ---------12%8!=0
结构体内存分配例子二:
1 strcut test2
char b[9];
测试可知:
[pengliang@www ]$ ./structlengthsizeof(struct test2)=16offsetof(struct test2)=0offsetof(struct test2)=4offsetof(struct test2)=13a占四个字节,b是一个数组,对于结构体中的数组,只需要查看它中的类型。因为b数组中存放的是char类型,char的对齐参数是1,所以这个数组中元素不管前面存放的是什么,b中第一个元素总是挨着前面那个元素。b占9个字节。同理:c是char 类型,紧挨在数组后面。4+9+1=14。前面使用到的所以对齐参数有:4和1,所以max(4,1)=4,结构体的总长度是4的倍数。c后面需要填充2个字节,为16
结构提内存分配例子三:
1 struct test3
short b[5];
&测试结果:
[pengliang@www ]$ ./structlengthsizeof(struct test3)=14offsetof(struct test3,a)=0offsetof(struct test3,b)=2offsetof(struct test3,c)=12
char的对齐参数为1,short的对齐参数为2。a占1个字节,因为short对齐参数为2,所以a后面填充一个字节,然后开始b数组,b一共10个字节。c紧跟b。所以暂时的长度为:1+1+10+1=13。
使用的所以对齐参数最大的为2,所以总长度要为2的倍数,c后面再添加一个空白字符。总共14字节。
经过上面三个例子,我们应该对基本数据类型的结构体的内存分配有了一定的了解,那么如果在结构体中还存在结构体成员呢?
我们有如下的处理规律:
  数组 :按照基本数据类型对齐,第一个对齐了后面的自然也就对齐了。 (其实前面已经证实了这个情况)  联合 :按其包含的成员中对齐参数最大的参数进行对齐。   结构体: 结构体中每个数据类型都要对齐,且结构体的对齐参数是结构体成员中对齐参数最大的。
来一个例子:
1 struct s1
7 struct s2
struct s1 struct1;
输出的结果为:
[pengliang@www ]$ ./structtestsizeof(struct s2) :16offsetof(struct s2,c) : 0offsetof(struct s2,struct1) :4offsetof(struct s2,e) :12
在s2中,第一个成员为c,占用一个字节。然后一个成员为struct1,那么struct1的对齐参数为:max(2,4)=4{取这个结构体中所有的对齐参数的最大值},所以需要在c后面填充3个字节。然后开始放struct1,因为struct1是结构体,所以按照结构体的分配方式:a占两个字节,由于long的对齐参数为4,所以a后填充两个字节,然后开始摆放b。b占四个字节。e占两个字节。所以暂时的总长度为1+3+2+2+4+2=14。在结构体s2中使用的所以的对齐参数有:1 、4 、2,所以s2的长度为4的倍数。在e后面添加两个字节。14+2=16;
再来一个例子:
1 struct s1
  & & struct s1 struct1[3]; & &
&[pengliang@www ]$ ./structtestsizeof(struct s2) :44offsetof(struct s2,c) : 0offsetof(struct s2,struct1) :4offsetof(struct s2,d) :40这个结果大家自己分析!!
联合(共同)体比较简单,我这里只举两个例子:
union test
sizeof(union test):8(取最长的嘛,肯定是double啊)
union test t1;
union test t2;
[pengliang@www ]$ ./uniontestsizeof(struct s):28offsetof(struct s,e):0offsetof(struct s,t1):8offsetof(struct s,f):16offsetof(struct s,t2):20好了,这些内容就说到这里了,可能很多人为什么一样的代码在自己的机器上面结果不要呢?这个前面我就说了,对齐的时候每一个编译器的默认对齐参数不一样,在vc中全部都是sizeof(type),所以double的默认对齐参数是8.但是在gcc中,类型大于等于4的类型全部是4,这就是区别。另外,我们可以通过这个指令来调整这个默认值:
#pragma pack(n)&&&& //n为对齐的默认字节数
#pragma pack(1)1 struct test3
short b[5];
6 }[pengliang@www ]$ ./uniontestsizeof(struct test3):12offsetof(struct test3,a):0offsetof(struct test3,b):1offsetof(struct test3,c):11由此可以看出,如果这个默认对齐参数越小,越有利于节约内存,但是可能会带来访问的效率问题。当n=1时,就是每一个变量都是一个挨着一个存放的!!!当默认对齐参数越大,占的空间就越多,主要是在8字的变量较多的情况下,但是这样的访问效率较好。这就是一个时间与空间的博弈!!
#pragma pack(8)
short b[5];
这个sizeof(s)在vc下编译,结果是24,a占一个字节,补一个空,b占10个字节,补4个字节(因为b要从8整数倍开始),最后8个字节的c。1+1+10+4+8=24.
但是这个#pragma pack(1)在gcc下面好使,但是#pragma pack(8)却不好使!!!
查看论坛得知:默认的对齐是按照 int 型(4字节)对齐,如果指定 #pragma pack(N) 中的 N 的话,N 不能大于默认对齐指定的长度,即如果默认对齐是 4 的话,N的取值可以是 1、2、4,超过 4 之后作为 4 处理。在 Windows 等系统上似乎没有这个限制。-------http://bbs.chinaunix.net/thread--1.html
那么怎么在gcc中设置一个结构体的存储对齐参数为8呢??
查找之后发现,在定义后面加上这个gcc特有的_attribute__机制即可:
#pragma pack(8)
short b[5];
9 }__attribute__ ((aligned (8)));这样就能得到和
[pengliang@www ]$ ./uniontestsizeof(struct test3):24offsetof(struct test3,a):0offsetof(struct test3,b):2offsetof(struct test3,c):12这样的话,在gcc中,这个存储结构也占用了24个字节。但是还是有点小问题:在vc中abc的偏移分别是:0、2、16.而在gcc中偏移量是0、2、12,呵呵,到这里,你应该能够分辨为什么会有这种区别了吧??
最后,好像扯得太远了,哈哈,我原来的目的是想知道dirent结构中d_reclen的内容是什么,现在看来这是so easy!!!!!!
4(d_ino)+4(d_off)+2(d_reclen)+1(type)+1(补位)+strlen(d_name)& 最后通过对齐参数4来修正总体的长度!
oh,my god,一天过了.........汗
本文除了前面一点点是借鉴了别人的内容外,后面的例子都是自己写的,如果你感觉还可以的话,就给个鼓励吧!
阅读(...) 评论()Linux 下c语言编程所引用/dirent
  LINUX系统下的一个头文件,在这个目录下/usr/include
  为了获取某文件夹目录内容,所使用的结构体。
  引用头文件#include&dirent.h&结构体说明  struct dirent
  long d_ /* inode number 号 */
  off_t d_ /* offset to this dirent 在目录文件中的偏移 */
  unsigned short d_ /* length of this d_name 文件名长 */
  unsigned char d_ /* the type of d_name 文件类型 */
  char d_name [NAME_MAX+1]; /* file name (null-terminated) 文件名,最长255字符 */
  }相关函数  (),(),();使用实例  #include &stdio.h& #include &errno.h&
  #include &string.h& #include &sys/types.h&
  #include &dirent.h&
  #ifndef DT_DIR
  #error &DT_DIR not defined, maybe d_type not a mumber of struct dirent!&
  #endif
  main(int argc, char*argv[])
  staticchar dot[] =&.&, dotdot[] =&..&;
  constchar*
  struct dirent *
  if (argc ==2)
  name = argv[1];
  name =
  dirp = opendir(name);
  if (dirp == NULL) {
  (void)(stderr, &%s: opendir(): %s: %s\n&,
  argv[0], name, (errno));
  exit(errno);
  while ((dp = readdir(dirp)) != NULL) {
  if (dp-&d_type == DT_DIR)
  if ( strcmp(dp-&d_name, dot)
  && strcmp(dp-&d_name, dotdot) )
  (void)printf(&%s/\n&, dp-&d_name);
  (void)closedir(dirp);
  return (0);
&|&相关影像
互动百科的词条(含所附图片)系由网友上传,如果涉嫌侵权,请与客服联系,我们将按照法律之相关规定及时进行处理。未经许可,禁止商业网站等复制、抓取本站内容;合理使用者,请注明来源于。
登录后使用互动百科的服务,将会得到个性化的提示和帮助,还有机会和专业认证智愿者沟通。
此词条还可添加&
编辑次数:4次
参与编辑人数:4位
最近更新时间: 17:48:05
贡献光荣榜4494人阅读
linux(12)
struct dirent
#ifndef __USE_FILE_OFFSET64
&&& __ino_t d_
&&& __off_t d_
&&& __ino64_t d_
&&& __off64_t d_
&&& unsigned short int d_
&&& unsigned char d_
&&& char d_name[256]; /* We must not include limits.h! */
注意其中的d_type字段。
/* File types for `d_type'. */
&&& DT_UNKNOWN = 0,
# define DT_UNKNOWN DT_UNKNOWN
&&& DT_FIFO = 1,
# define DT_FIFO DT_FIFO
&&& DT_CHR = 2,
# define DT_CHR DT_CHR
&&& DT_DIR = 4,
# define DT_DIR DT_DIR
&&& DT_BLK = 6,
# define DT_BLK DT_BLK
&&& DT_REG = 8,
# define DT_REG DT_REG
&&& DT_LNK = 10,
# define DT_LNK DT_LNK
&&& DT_SOCK = 12,
# define DT_SOCK DT_SOCK
&&& DT_WHT = 14
# define DT_WHT DT_WHT
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:61681次
排名:千里之外
转载:55篇
(1)(2)(2)(1)(1)(2)(2)(3)(1)(5)(4)(3)(1)(2)(3)(4)(1)(3)(5)(8)(8)

我要回帖

更多关于 哈大高铁为什么是d 的文章

 

随机推荐