[apue] Linux / Windows 系统上只能建立不超过 PATH_MAX / MAX_PATH 长度的路径吗?资料

本文主要介绍[apue] Linux / Windows 系统上只能建立不超过 PATH_MAX / MAX_PATH 长度的路径吗?资料 方法和在新技术下所面对的“挑战”,方便大家深入理解[apue] Linux / Windows 系统上只能建立不超过 PATH_MAX / MAX_PATH 长度的路径吗?资料 过程。本文也将分享[apue] Linux / Windows 系统上只能建立不超过 PATH_MAX / MAX_PATH 长度的路径吗?资料 所遇到的问题和应对策略,怎么解决怎么做的问题。
通过深入本文可以理解代码原理,进行代码文档的下载,也可以查看相应 Demo 部署效果。

这个最大路径长度是为了方便程序编写?还是说底层的文件系统就只能支持这么长的路径呢?本文为你揭开谜底

问题的提出

在处理文件系统路径的时候,我们一般会先开辟一块内存区,用来接收路径、或者拼接好路径传递给系统调用。这是因为路径在各个系统上都有最大长度限制,在 Windows 上这个值是 MAX_PATH,一般不能超过 260;在 Linux 上这个值是 PATH_MAX,一般不能超过 4096 (或者通过 pathconf (_PC_PATH_MAX, …) 来获取,但是一般也是 4096),就像下面这段典型的代码:

 1 int main ()  2 {  3 #ifdef WIN32  4     char buf[MAX_PATH + 1] = { 0 };  5     if (GetModuleFileNameA(NULL, buf, MAX_PATH) == 0)  6     {  7         printf("get current module path failed, errno %d", GetLastError());  8         return -1;  9     } 10 #else 11     char buf[PATH_MAX + 1] = { 0 }; 12     if (readlink("/proc/self/exe", buf, PATH_MAX) < 0) 13     { 14         printf("read exe path failed, errno %d", errno); 15         return -1; 16     } 17 #endif 18  19     printf("current executable file path: %sn", buf); 20     return 0;  21 }

 

它用来获取当前可执行文件的完整路径。在 Windows 与 Linux 上分别调用了 GetModuleFileName 与 readlink 系统调用,且事先在栈上分配了接收完整路径的内存区 buf。最后将成功获取的路径打印到控制台。在两种系统上,输出分别如下:

Windows

current executable file path: E:codeapue2.chapterReleasepath_max.exe 

 Linux

current executable file path: /home/yunhai/code/apue/02.chapter/path_max 

 

其它与路径相关的调用也是类似的。那么问题来了,这个最大路径长度是为了方便程序编写 (不然需要动态分配内存,且需要两次调用,其中一次用于获取最终的路径长度),还是说底层的文件系统就只能支持这么长的路径呢?

问题的验证

为了弄清楚这个问题,我专门写了一个测试程序:

path_max.c

  1 #ifdef WIN32   2 #  ifndef _WIN32_WINNT            // 指定要求的最低平台是 Windows Vista。   3 #  define _WIN32_WINNT 0x0600     // 将此值更改为相应的值,以适用于 Windows 的其他版本。   4 #  endif   5 #include <windows.h>    6 #include <direct.h>    7 #else    8 #include <limits.h>   9 #include <unistd.h>   10 #include <fcntl.h>   11 #include <errno.h>   12 #include <sys/stat.h>   13 #endif   14 #include <string.h>  15 #include <stdio.h>   16 #include <stdlib.h>   17 #include <time.h>  18   19 void get_random_name (char *name, int len, int level)  20 {  21   int i, n;   22   sprintf (name, "%d", level);   23   n = strlen (name);   24   for (i=n; i<len; ++ i)  25     name[i] = rand () % 26 + 'a';   26   27   name [len] = 0;   28 }  29   30 int main (int argc, char *argv[])  31 {  32   int dir_len = 0, file_len = 0;   33   char *name = 0;   34   int ret = 0, level = 0;   35 #ifdef WIN32  36   int name_max = MAX_PATH;   37   int path_max = MAX_PATH;   38   HANDLE fd = 0;   39 #else   40   char const* path = "/";   41   int name_max = pathconf (path, _PC_NAME_MAX);   42   int path_max = pathconf (path, _PC_PATH_MAX);   43 #endif   44   45   printf ("NAME_MAX = %d, PATH_MAX = %dn",   46     name_max, path_max);   47   48   // add 1 (/) to 10 to be conveniently to compute how low the path is with level.  49   dir_len = 9;   50   file_len = 100;   51   52   srand (time(0));   53   name = (char *) calloc (1, (dir_len > file_len ? dir_len : file_len) + 1);   54   if (name == 0)  55     return -1;   56   57   58   do  59   {  60     get_random_name (name, dir_len, ++level);   61 #ifdef WIN32  62     //ret = _mkdir (name);   63     //if (ret == -1)  64     ret = CreateDirectory(name, NULL);   65     if (!ret)  66     {  67       printf ("CreateDirectory %s failed, errno = %dn", name, GetLastError ());   68       break;   69     }  70 #else   71     ret = mkdir (name, 0777);   72     if (ret == -1)  73     {  74       printf ("mkdir %s failed, errno = %dn", name, errno);   75       break;   76     }  77 #endif   78       79     printf ("mkdir %sn", name);   80 #ifdef WIN32  81     //ret = _chdir (name);   82     //if (ret == -1)  83     ret = SetCurrentDirectory(name);   84     if (!ret)  85     {  86       printf ("SetCurrentDirectory %s failed, errno = %dn", name, GetLastError ());   87       break;   88     }  89 #else   90     ret = chdir (name);   91     if (ret == -1)  92     {  93       printf ("chdir %s failed, errno = %dn", name, errno);   94       break;   95     }  96 #endif   97   98     //printf ("change to that dirn");   99     get_random_name (name, file_len, level);  100 #ifdef WIN32 101     fd = CreateFile (name, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, 0, 0);  102     if (fd == INVALID_HANDLE_VALUE) 103       printf ("open %s failed, errno = %dn", name, GetLastError ());  104     else  105     { 106       printf ("open %s OK.n", name);  107       CloseHandle (fd);  108     } 109 #else  110     int fd = open (name, O_RDWR | O_CREAT, 0644);  111     if (fd == -1) 112       printf ("open %s failed, errno = %dn", name, errno);  113     else  114     { 115       printf ("open %s OK.n", name);  116       close (fd);  117     } 118 #endif  119   } while (1);  120  121   free (name);  122   return 0;  123 }

 

这个小程序很简单,每次创建一个目录,切换进去,创建一个文件。这样周而复始,直到出错退出。目录名长度固定为 9,这样加上目录分隔符(/ 或 )就正好凑成 10,方便之后根据目录深度计算路径总长度;文件名长度固定为 100,也是为了方便计算路径总长度。每个名字都是由 26 个字母随机组成的,同时将目录深度 (level)记录在名字开始。例如第 10 级目录可能长这样:“10jmvrfqv”,前面的数字 10 明确的标识了目录层级,同理,文件名前面也是层级数字,也是为了方便计算。好了,我们分别在两个系统上跑一下这个测试程序。

1. Windows 上的结果 ( Win10 x64)

NAME_MAX = 260, PATH_MAX = 260 mkdir 1tdobxciu open 1gybhgvdtngozbkzvcuvpnitcpntxgtjhasljfycfowuuqmcvvitsthzdxpckttobaqtccxeabfmnvhoeknyjifabnynkrjwzhiq OK. mkdir 2wafsehgp open 2ssywxcafcvpuppgxjcpctjkleftvyhwpuzydlcaaxkbsgumljccmokznqpkvliklndweyegqxvmrmtcrfwzqyllezvneztvqwma OK. mkdir 3vmkjwgrp open 3bclyodmcwjgzmokchhkrmharodswgmpbusxozgqogaguvppohpthetfgqxrmihdjjmqsxvdzgondfsirxfmqbmgmexdnbdjyrqr OK. mkdir 4xmvhqrfh open 4hclzbqzoniuuolhumysibxonqutbpqgvroamdwdorhypsfkrkyskqykdukfrngtfipgjidvazgsvdfejofbjqqwpthkfxzgwubw OK. mkdir 5rwoxiiwh open 5sdeemddmvkhszsubkojdemrconicercdpdcmsmitbbuxowvsqbfghagpwkgmdrytzfnafoqvwsktiwdkjskfukxtxjeknctdjcm OK. mkdir 6fnmlhdor open 6vjrqxecbutxcospyzihwjabulwzbvbwimubvvchdxgyhqfjebjnpbbhvtwrkjlowmzbpoqkshwjbzoqysxfthztefvzwgarrdon OK. mkdir 7sbvhcsxw open 7ddmdylgkhghdeefydnjfsmiyxwutewbmujsppdezpoamtwodvqvkyaeswywbfnvjctofiaftmkiwapbjawuhjvuqsmefjpfgbew OK. mkdir 8dwhpsgaj open 8xepfibfufsaefmghnjukuddbqhyijunkazscfjxkznnylylpcaiauwyrzcfixbjfguvimzwrabcnvxomkaelrwtgnhsjxpiwmii OK. mkdir 9wmpqcalh open 9ldugmypucabxtjnpxqdvinxtevztnspuakrwwhebpshzsgbkedvmxbibkwyaoxctfelwjsglvdwjfjffuleijofuoinnrdcdymf OK. mkdir 10vlwydie open 10jihhaxrcpsviddxserikiiyrtbiwdumzdsyhkkodreimjxivkpnnxxtgpuathmqatlajmfueupwsdwjhyferopxiqggkywccvz OK. mkdir 11awvhauw open 11ypsctazqpuebetmzzgrzasmjmzppymtdabgcajahhwuwilzxlgvpupuksrjtmigjogjyqxhczuunlknxupfixnyxlyjsdhgwuf OK. mkdir 12pdznsnw open 12easlcjvcdudtktfkseedbtlbvnjhjtlchtjbbshmjbdsnpifidqjwsttalzwlyjezixtghwortsusrifigbxhpznmiigtvviym OK. mkdir 13pvvjtcb open 13lbpsmpbwyzzcnjlixarmvbxpqeketgycbduhzlhhakxykncmxwhmgqrwigcywiehemmhlinrhxnxbktentpvnlazrzgniwgcnf OK. mkdir 14jrhanvs open 14nlvfzgxyfzekthrzidzoeugldefwnxlelbntfetdnxvxkcupkpnzxhytidycrstkchdojzrsdjxclkvfgvmmsenysyyinkylsd OK. mkdir 15yilwbim open 15dhjbeoeybggfrjpstbyobosrmigtfhmpbajgwhjgczgklphxweefjoliwbuabyxyfsnzjzpiaxdagfbkujrqistslqkffqmilx OK. mkdir 16owgedmp open 16cqauvpdzsghgmzdbdxaqdclrvuyophifemvsoygwuhbtlkkmwmwxekwcxgmauagexxtyirthfgjbztmutljstjiwcbwmntkfri failed, errno = 3 mkdir 17xljxtht open 17umkwtdbxiayekrljssfnxgvcmytthwevlmrxptivqmvwrkpqkvxoircuwadhkyidoaydlvnnafejpssqdewcymluzmrwrrkwmn failed, errno = 3 mkdir 18aywtihk open 18ynydjmncmakzoezcupoeqfiahsunxhqvczbuapntehglrrhubpbydnnpnbpjdschmrkzkkpvgfajemsfsvofsjoclijforjkex failed, errno = 3 mkdir 19qsvtxwm open 19qpfdrjgnxthljturhvuymuoqctsmixxrircoievqpgrnxpzufozwvpsjocdxfhjodpfzljbgegutfsquaehjoaswqhwtsqbgmh failed, errno = 3 mkdir 20vzvuovy open 20zqqxsfnxrccsubxwevfffunrxfugkovltzidalrmppjjyrbnohxgmwnmwcseijuhzabngyfodgodnblmvhmvnmkvqfijucfqfz failed, errno = 3 mkdir 21idgwupz open 21vlkqahypwulaaykizzvqviqztswdwikvloswluydfyqmgjcaixqqrilsrjireprfrvbgfvspulfmnuksbvsnfkdncybuhxddtw failed, errno = 3 mkdir 22plbyhbe open 22rbekcixmxcohnvqlyhlppmgqtpsgsjwxhuwlmhnzspkbvdrnzechjbjsglzajiadiqguutgfjfkaqdtfqeevpcrsejiiotytse failed, errno = 3 mkdir 23vggwvra open 23tlbobatwbdpaxouojluctxqyddllqedqbeotpkkxgddristpprablooxlomgvneixubhxhemtlvipqwzzfgqcxjtdltytpialw failed, errno = 3 mkdir 24dkpkfup open 24fujnicyzpudgnsuzcqkkgihsousejefcuepnkkxdpdxbxxfryeglrmikgxxckazfokmdrgttnqxavphpoekagfbenjyuxpfntu failed, errno = 3 CreateDirectory 25aajjgcq failed, errno = 206

 

我是在 G: 根目录运行这个程序的,跑到第 16 级目录时,CreateFile 失败返回了,错误码为 3 (ERROR_PATH_NOT_FOUND:系统找不到指定的路径),对于文件创建失败,这里忽略,所以程序继续运行;跑到第 25 级目录时,CreateDirectory 也失败返回了,错误码为 206 (ERROR_FILENAME_EXCED_RANGE:文件名或扩展名太长),因为不能再继续了,所以整个程序终止。看了一下,到 16 级目录时整个路径是这样:

[apue] Linux / Windows 系统上只能建立不超过 PATH_MAX / MAX_PATH 长度的路径吗?

 

总长度达到 162,此时如果想再创建文件的话,总长度会升至 162 + 1 + 100 = 263  > MAX_PATH,所以接下来的文件创建失败了。然后再看下到 24 级目录时路径的样子:

[apue] Linux / Windows 系统上只能建立不超过 PATH_MAX / MAX_PATH 长度的路径吗?

 

总长度达到 243,如果再加上一个目录的长度的话,应该是253 < MAX_PATH,按理说应该还可以容纳一个目录的创建,但是我实地在这个目录下面尝试创建目录,得到了这样的错误:

[apue] Linux / Windows 系统上只能建立不超过 PATH_MAX / MAX_PATH 长度的路径吗?

 

如果是创建文件的话,会发现输入一定长度的文件名之后,就输入不了了:

[apue] Linux / Windows 系统上只能建立不超过 PATH_MAX / MAX_PATH 长度的路径吗?

 

这个长度目前是 16 (算上后缀 .txt 4个字符),加上之前目录的长度 243,总长度为 243 + 1 + 16 = 260,正好等于 MAX_PATH。可见,对于 Windows 而言,这个 MAX_PATH 就是底层文件系统的限制,再怎么玩也玩不出这个杠杠。尝试切换 CreateDirectory / SetCurrentDirectory  实现为 _mkdir / _chdir,看看有什么不同 :

line 62-65

    ret = _chdir (name);      if (ret == -1)     //ret = SetCurrentDirectory(name);      //if (!ret) 

line 81-84

    ret = _mkdir (name);      if (ret == -1)     //ret = CreateDirectory(name, NULL);      //if (!ret) 

 

重跑上面的例子,会得到完全一样的结果。

2. Linux 上的结果 (neokylin x64)

一开始我是在 CentOS i686 环境上跑的,没想到一阵跑之后再回来看,虚拟机桌面居然重置了,所有 shell 都退出了,没有截到任何输出,无奈只好采用另一个平台了。在这个中标麒麟的环境跑完了全程:

$ ./path_max NAME_MAX = 255, PATH_MAX = 4096 mkdir 1rkxtumwh open 1tovmschzmqujtonfqbqyfomyykrtwqcrezfxbmypesyygmfxpvxvjmvkwnfudhnhgsghgfwkzxkgjpfamcxwotimgniluvucpbl OK. mkdir 2vijihgsn open 2rkuswxpuniccqrkbliwpzzaxhkfqqzgklackzrgpclrscduqnsfnrikasrqkswuexwqwqwlshekkigaxyhkrpwrjniuieqodnea OK. mkdir 3fanxiuju open 3cqwzqdmivizeyjygopureytlajkkdtehlciegumddnhdxgjnxfedfaofjysmtytfbbjjyxmdmtgjbrwywdddfrkopcclbxqcabn OK. mkdir 4yazbmsjy open 4wawuybydgrowjqyutxmxynkypjcbelzaowwoxwsgqiczabtuaftyuezjpbmvomxekutjsnpixuhxxctxhnwdtvmiybemnbrzxmk OK. mkdir 5sbcaywkx open 5torqwgobzlqjlrnygrrhqdrigvletvbmjufhcvldjbnuscuavlhmqawwwhcpegeqalzfgkirnvmfaghvuojkpghlnlcsrgkurjz OK. mkdir 6aujthffp open 6howeinoseubrjntbgclavxzxrjraqwrzmqdudrphnsaxhtaovootlqqebheteysqoxntpccewcbevcstqimbacfbklwqjqixovs OK. mkdir 7fzujwwnc open 7upunhebiffpircfhmxsllpespacnxpptglgnrjxyoohgqopclhqzxuroutdtkumshufydexusgcjwtnhbdiaxaquvvnircaywgy OK. mkdir 8cmxwffao open 8btdlwhtygtqaplqxcszcofbsuyqzeqphmssizmjgfziwlyvpsvsjcvbwtsxzkmhwhzhinqovrztezpusmodqjepeyoejdnhkoos OK. mkdir 9cgjxyiqe open 9jhydvmgovlfaltguwvegjubndkmbufhdoghmupasahuoackzxohijiwmukpopwueedqbsstvzpjbrtcokkyvuujrfahwwbcdeue OK. mkdir 10xmzunod open 10rfytviftdcqmtxmatlewqkqujfvdsjgjqffnpkgtoyhhvwkrhqnxaftkmqphbysrdxeukmpylxigtuxckmbmuwyimopnmkgrjk OK.  ……  mkdir 1341932sc open 1341932rlcbgduqybifdacrgopzdnulnwxjtrlldpmltibrjlzolbhuqytvnpgbmgmhzzscpfniprbbearsezmuxhrnwaqkgcsfb OK. mkdir 1341933kk open 1341933qrzyhsckxcbpgcdcckupgufrchjjivvbnvbwndgmgjdomgroqndzjiqnrbwbwuclpejejrtrbwgndzdvoguxqmkhpikoc OK. mkdir 1341934nz open 1341934ttlyecrwdpcssdvqrdmovzaeqipeneggxrgbvxzzpbthgrzxwmnsnnwdylilpotohasczrdovzybqxzmjmewcdaaokngy OK. mkdir 1341935gu open 1341935hgmjgenwzmuaesbsbozaqccsqmfwmnttufcclrykfvnjnocqebswduovgvusjnlduqhghhspcfypuciafaxivlgdhcwqr OK. mkdir 1341936jv open 1341936lzerjlkaqryhndpoisltnwzqfdoxuysfzyzkklkccljqozgyrrrgpsyvvnupnpxonwbzjlblyldomjndcglszlpwyjony OK. mkdir 1341937le open 1341937ojfnsspftcjhouwtxderepgcqrqfsdjgmqvejmkcovlcpivonbfttnvjhmqzpahcqeibruffrrijbfxojfhcuelbqdcgd OK. mkdir 1341938lk open 1341938wquzhrfoiyytzerpnyyrscewvhadnmplejkncrblpaeqgxhtxhkqkoohxokkczvikgvnzxarxghderybyktkajrxybkca OK. mkdir 1341939fl open 1341939lnganfaecgnhmehqftjpvthvtkfvlkiyypynuarzggitnsjsluhhpqckbjgotootfogcoxduglptfylrvuaklevondeit OK. mkdir 1341940sc open 1341940bgiduigqotghzgssbmuozylpnqtvjlzktipnqxggrmnsshkwvekvevmtngqwtqjnaacsyiyruljpstlnzxkfuxyhfodyg OK. mkdir 1341941ol open 1341941gpqypywgvhpkbkxrlubqoaovfeaelprrghqvimbdwspzemqpgshwsvrabrgmixgohyjpmmuigjikxybfsibnfunjltvws OK. mkdir 1341942dk failed, errno = 28

 

中间输出比较多,就省略了,只显示前后十几行内容。我是在 /home/vmware/code/apue/02.chapter 目录下运行这个程序的,跑到 1341942 级目录时,mkdir 失败返回了,错误码为 28 (ENOSPC:No space left on device)。总的目录路径长度达到 34 + 1341941 * 10 = 13419444,最深层的一个文件总路径长度达到 34 + 1341941 * 10 + 100 = 13419544,都远远大于 PATH_MAX (4096)了。此时我在运行程序的目录新建文件或目录,都会失败。

$ mkdir abc mkdir: 无法创建目录"abc": 设备上没有空间  $ touch abc touch: 无法创建"abc": 设备上没有空间 

 

所以可以肯定的一点是,Linux 上的 PATH_MAX 并不是底层文件系统对路径最大长度的限制,只是一种便于程序编写的常量。那路径的最大长度到底由什么决定呢?看了上面 ENOSPC 的错误码,我第一反应是硬盘空间满了,然而在查看了磁盘剩余空间后,我否决了这个可能性。下面是我在执行测试程序前后分别记录的 df 输出。

[apue] Linux / Windows 系统上只能建立不超过 PATH_MAX / MAX_PATH 长度的路径吗?

 

可以看到所在的 /home 挂载点使用比例激增 (8%~22%),但是也没有达到 100%,所以磁盘空间还是比较充足的,很可能只是 inode 用光了(?)。不管怎样,本质上都是一种资源限制,这使得程序员可以在 Linux 上创建比较长的文件路径,比 Windows 提供了更大的灵活性。但是这样长的路径并不被所有程序所识别,例如,我在刚才创建测试目录的地方,递归列出所有文件,输出如下:

$ ls -R .: 1rkxtumwh  Makefile  name_max.c  path_max    path_max.o    path_max.vcxproj apue.o     name_max  name_max.o  path_max.c  path_max.sln  ./1rkxtumwh: 1tovmschzmqujtonfqbqyfomyykrtwqcrezfxbmypesyygmfxpvxvjmvkwnfudhnhgsghgfwkzxkgjpfamcxwotimgniluvucpbl 2vijihgsn  ./1rkxtumwh/2vijihgsn: 2rkuswxpuniccqrkbliwpzzaxhkfqqzgklackzrgpclrscduqnsfnrikasrqkswuexwqwqwlshekkigaxyhkrpwrjniuieqodnea 3fanxiuju  ./1rkxtumwh/2vijihgsn/3fanxiuju: 3cqwzqdmivizeyjygopureytlajkkdtehlciegumddnhdxgjnxfedfaofjysmtytfbbjjyxmdmtgjbrwywdddfrkopcclbxqcabn 4yazbmsjy  ./1rkxtumwh/2vijihgsn/3fanxiuju/4yazbmsjy: 4wawuybydgrowjqyutxmxynkypjcbelzaowwoxwsgqiczabtuaftyuezjpbmvomxekutjsnpixuhxxctxhnwdtvmiybemnbrzxmk 5sbcaywkx  ./1rkxtumwh/2vijihgsn/3fanxiuju/4yazbmsjy/5sbcaywkx: 5torqwgobzlqjlrnygrrhqdrigvletvbmjufhcvldjbnuscuavlhmqawwwhcpegeqalzfgkirnvmfaghvuojkpghlnlcsrgkurjz 6aujthffp  ./1rkxtumwh/2vijihgsn/3fanxiuju/4yazbmsjy/5sbcaywkx/6aujthffp: 6howeinoseubrjntbgclavxzxrjraqwrzmqdudrphnsaxhtaovootlqqebheteysqoxntpccewcbevcstqimbacfbklwqjqixovs 7fzujwwnc  ./1rkxtumwh/2vijihgsn/3fanxiuju/4yazbmsjy/5sbcaywkx/6aujthffp/7fzujwwnc: 7upunhebiffpircfhmxsllpespacnxpptglgnrjxyoohgqopclhqzxuroutdtkumshufydexusgcjwtnhbdiaxaquvvnircaywgy 8cmxwffao  ./1rkxtumwh/2vijihgsn/3fanxiuju/4yazbmsjy/5sbcaywkx/6aujthffp/7fzujwwnc/8cmxwffao: 8btdlwhtygtqaplqxcszcofbsuyqzeqphmssizmjgfziwlyvpsvsjcvbwtsxzkmhwhzhinqovrztezpusmodqjepeyoejdnhkoos 9cgjxyiqe  ./1rkxtumwh/2vijihgsn/3fanxiuju/4yazbmsjy/5sbcaywkx/6aujthffp/7fzujwwnc/8cmxwffao/9cgjxyiqe: 10xmzunod 9jhydvmgovlfaltguwvegjubndkmbufhdoghmupasahuoackzxohijiwmukpopwueedqbsstvzpjbrtcokkyvuujrfahwwbcdeue  ./1rkxtumwh/2vijihgsn/3fanxiuju/4yazbmsjy/5sbcaywkx/6aujthffp/7fzujwwnc/8cmxwffao/9cgjxyiqe/10xmzunod: 10rfytviftdcqmtxmatlewqkqujfvdsjgjqffnpkgtoyhhvwkrhqnxaftkmqphbysrdxeukmpylxigtuxckmbmuwyimopnmkgrjk  ……  410dntuzt ls: 无法打开目录./1rkxtumwh/2vijihgsn/3fanxiuju/4yazbmsjy/5sbcaywkx/6aujthffp/7fzujwwnc/8cmxwffao/9cgjx yiqe/10xmzunod/11ltybuja/12pddukks/13pgjmtme/14yxyuhvt/15qgddfps/16ipghtsx/17hrlvjqw/18mlwamyj/19ycqq oum/20gdekplr/21mgkqtef/22uxjelyo/23yuogjxv/24gdyuetr/25ekyseyq/26mohxeho/27yhfufeo/28emftmwp/29detfm nz/30ulhqorq/31lzvmcau/32vrkdiho/33pwrixvt/34ysjlzxm/35anbimen/36aazpcto/37dpzcvhb/38vbxsrwc/39urooly a/40gabvtkg/41fswpnkc/42eyozjbb/43mbsphto/44szukcad/45lobskag/46njddwrk/47qmyaqip/48qywwpge/49jymbads /50cevctwp/51dbrvvrg/52alaqbak/53wdxytcx/54iajcocc/55yulgnls/56xdvlohr/57rsyzzme/58avlsjct/59kzwpnmn/ 60zuuyott/61cmyywqh/62fyuzvce/63djljats/64aopcwyi/65rxefdvy/66egqsclw/67jxyausw/68atlilhv/69xrxqsel/7 0isglkct/71fwkjdms/72mhygulk/73nlnwbrx/74sroynrd/75dimglds/76ulettre/77cvdbchx/78imrnssw/79uqfezsr/80 lkhipxs/81rbdpqqz/82lvyzxqt/83sgxgrxx/84tsgcvwa/85jaamdba/86zoneybo/87glbanpe/88tkzaefg/89rrwsack/90u owxuoq/91rabkpyi/92dcnxiyz/93lacaahs/94frjwezd/95yhtpnte/96fblotmh/97mibhekj/98rzonuec/99topwrdn/100d blgkn/101drisrx/102aqjjso/103uefcom/104yrflxq/105hyfxyh/106tlpbnl/107ndiswq/108uvgksb/109ozcwup/110qx pxlo/111gttfdp/112nepxhw/113xwflah/114yibgjy/115dffvxj/116ukiosf/117fpvyvt/118kdreee/119ejgwiz/120lpo qvc/121gihnlr/122umltry/123ajaaeq/124unorwj/125iuipco/126uwghec/127lzrzvo/128zytdwi/129xvkgeh/130mgfx pr/131kekuik/132fjlbpy/133wogrgw/134eotsoo/135fquige/136smcyju/137obzwup/138fewkay/139dgizof/140gqrvp w/141lwxiji/142gprlwz/143geyxsn/144otqwya/145ooyfvk/146ucigye/147xstuji/148ziprio/149ufrzci/150lmgpli /151kczfla/152svbdit/153fzlyns/154yirhkv/155xbdixx/156mogbae/157goxflw/158fixfsg/159ncihug/160bnrvsj/ 161ynpfeh/162cmanrm/163utjekr/164qcvzim/165ypxvkh/166ggnvdw/167nszvsr/168uyuayf/169fatffy/170znjsdj/1 71jqobhe/172syewyj/173fbdzgu/174bufnki/175qasxqn/176rigmyh/177zwoexf/178bdrxbg/179ggdmzx/180ljyrtm/18 1qbywid/182wsjhtx/183moknmr/184haaeaa/185jdpxza/186eerxfa/187kpfjiq/188wrdbbh/189uuhvct/190ofpwct/191 qnmtmy/192gqyowy/193eckugg/194oonhah/195dbjuxd/196qzbvuh/197kcqziu/198akbhoa/199hkszfc/200aqieum/201a hkuqb/202hkikbi/203gywiex/204ibfmca/205vgczdp/206pchnch/207tfkxlo/208orztrq/209foperp/210umtatf/211rf qqzo/212xuspzm/213bsqdet/214kbvvmg/215qsbepc/216qqqvea/217mtyasr/218eunbgv/219stppxz/220ncqzlb/221qgl ips/222naqylv/223ymrfpk/224vavwhr/225dznual/226iuraac/227ztobic/228jynnfd/229iatquu/230vuokzi/231ykpc bl/232wqldxe/233qeebyv/234nvspvv/235iqxfye/236nwnztb/237qjtgnn/238qyzyas/239lhcqon/240piorsv/241upvvm j/242sjgemx/243ndojai/244whhuvw/245hmojut/246kwaiwh/247ohckmb/248ucmdrh/249eqzimi/250uymmqd/251cnglst /252iysywl/253jridil/254nmoqzh/255ygguhk/256nwuiap/257zvtolc/258urycli/259kpiuab/260jempzc/261jyqcbe/ 262sulagk/263mvljld/264ciiawa/265vjxora/266rxfgkg/267jwvpoy/268mpmgja/269xpxycf/270fjxobt/271zahncm/2 72soljdu/273jcdwrq/274wvrusy/275noyexu/276oksjfe/277wzfwvr/278tcsfue/279uhzgjs/280lfpypw/281cyjibv/28 2jwnlgu/283nnktxs/284udmuma/285xzbwnj/286jemqma/287xnedax/288dcvfle/289ddnbqe/290jheimg/291rscgbr/292 zlyhgw/293jbmjzx/294qocgsi/295mbyvyj/296ntwpkk/297jhofrm/298ibirpc/299kquens/300mbjnmo/301najyhm/302g yerut/303blongi/304tafajx/305suvetf/306faeoiu/307dunnih/308ifvtsq/309vulqxe/310ilvtjv/311gzknfk/312ju xeni/313bpaezt/314dcqgbb/315rqnuic/316ejhbrb/317wfzvzo/318hfndtr/319zgsznw/320dqahuh/321mdnyne/322xiu lms/323lplrvo/324qtvodk/325tiigxk/326kljzob/327lxxopm/328qwjlms/329jwcbic/330nowwgr/331jqqbce/332qael pn/333vyyvlr/334wvchpm/335afdbpb/336vsrvym/337ktyfii/338gasxaz/339gjjnco/340yqdxcc/341eysxtl/342ipsoc o/343xrjucz/344aoetoq/345rtnyzv/346ptrthp/347gnxqkl/348vfpcrp/349jmoobg/350glqvzi/351vkznzy/352cmjseg /353zgxeyh/354vfkgth/355fnhgjo/356cyouso/357hruehw/358jadbhv/359hklsla/360hwsife/361ragklc/362xydtpr/ 363tjrhwj/364gpsojy/365sphazl/366fgwang/367tovqhr/368ybyzbe/369wasspn/370jjkehg/371fvmqie/372bdigtd/3 73afocqc/374agluqq/375jlrfsu/376gtbemx/377lqbrlg/378xmxxvu/379pwznpd/380gdryol/381cgzdfe/382egzxfd/38 3ciccll/384mpoifm/385ygdqiy/386ahilzb/387bhmyia/388cmfhah/389kuxsqg/390winlgk/391jnjlim/392vurqut/393 yehkub/394vkgknd/395pxnmgr/396bsnizx/397bzbbbs/398kdfjjs/399ugopik/400klxzic/401kaqhcd/402iyrruo/403d tncvg/404feosyw/405cbohnn/406hfirse/407tqbohz/408udrjbo/409yhmpsz/410dntuzt: 文件名过长

 

中间输出比较多,就省略了。跑到 410 级目录时,ls 报错了,上一级目录路径的总长度达到 34 + 409 * 10 = 4124,其实已经比 PATH_MAX 大了,不过还是因为缓冲区不足而中断退出了。再尝试查找文件,输出如下:

$ find . . ./name_max.o ./path_max.c ./Makefile ./name_max ./path_max ./path_max.o ./name_max.c ./1rkxtumwh ./1rkxtumwh/1tovmschzmqujtonfqbqyfomyykrtwqcrezfxbmypesyygmfxpvxvjmvkwnfudhnhgsghgfwkzxkgjpfamcxwotimgniluvucpbl ./1rkxtumwh/2vijihgsn ./1rkxtumwh/2vijihgsn/3fanxiuju ./1rkxtumwh/2vijihgsn/3fanxiuju/3cqwzqdmivizeyjygopureytlajkkdtehlciegumddnhdxgjnxfedfaofjysmtytfbbjjyxmdmtgjbrwywdddfrkopcclbxqcabn ./1rkxtumwh/2vijihgsn/3fanxiuju/4yazbmsjy ./1rkxtumwh/2vijihgsn/3fanxiuju/4yazbmsjy/5sbcaywkx ./1rkxtumwh/2vijihgsn/3fanxiuju/4yazbmsjy/5sbcaywkx/6aujthffp ./1rkxtumwh/2vijihgsn/3fanxiuju/4yazbmsjy/5sbcaywkx/6aujthffp/6howeinoseubrjntbgclavxzxrjraqwrzmqdudrphnsaxhtaovootlqqebheteysqoxntpccewcbevcstqimbacfbklwqjqixovs ./1rkxtumwh/2vijihgsn/3fanxiuju/4yazbmsjy/5sbcaywkx/6aujthffp/7fzujwwnc ./1rkxtumwh/2vijihgsn/3fanxiuju/4yazbmsjy/5sbcaywkx/6aujthffp/7fzujwwnc/7upunhebiffpircfhmxsllpespacnxpptglgnrjxyoohgqopclhqzxuroutdtkumshufydexusgcjwtnhbdiaxaquvvnircaywgy ./1rkxtumwh/2vijihgsn/3fanxiuju/4yazbmsjy/5sbcaywkx/6aujthffp/7fzujwwnc/8cmxwffao ./1rkxtumwh/2vijihgsn/3fanxiuju/4yazbmsjy/5sbcaywkx/6aujthffp/7fzujwwnc/8cmxwffao/8btdlwhtygtqaplqxcszcofbsuyqzeqphmssizmjgfziwlyvpsvsjcvbwtsxzkmhwhzhinqovrztezpusmodqjepeyoejdnhkoos ./1rkxtumwh/2vijihgsn/3fanxiuju/4yazbmsjy/5sbcaywkx/6aujthffp/7fzujwwnc/8cmxwffao/9cgjxyiqe ./1rkxtumwh/2vijihgsn/3fanxiuju/4yazbmsjy/5sbcaywkx/6aujthffp/7fzujwwnc/8cmxwffao/9cgjxyiqe/10xmzunod ./1rkxtumwh/2vijihgsn/3fanxiuju/4yazbmsjy/5sbcaywkx/6aujthffp/7fzujwwnc/8cmxwffao/9cgjxyiqe/10xmzunod/10rfytviftdcqmtxmatlewqkqujfvdsjgjqffnpkgtoyhhvwkrhqnxaftkmqphbysrdxeukmpylxigtuxckmbmuwyimopnmkgrjk  ……

 

最后有没有完成我没有得到结论,因为整个虚拟机历时 N 天这个命令还没跑完 (N > 10),运行中的 find 截图为证:

[apue] Linux / Windows 系统上只能建立不超过 PATH_MAX / MAX_PATH 长度的路径吗?

 

我是按内存占用从高到低排序的,可以看到经过 N 天的运行 find 命令的内存占用已经超过了整个图形界面(Xorg),另外与 find 命令关联的终端 (mate-terminal) 内存、CPU也在高位运行。不过至少可以说明 find 并没有使用 PATH_MAX 来简单限制路径长度,可能是通过动态分配内存来实现对长路径支持的。另外个人比较好奇这个命令的句柄开支,于是看了下 lsof 的输出:

$ lsof -p `pidof find` COMMAND    PID   USER   FD      TYPE DEVICE  SIZE/OFF    NODE NAME find    113339 vmware  cwd       DIR    8,5      4096 2095005 /home/vmware/code/apue/02.chapter find    113339 vmware  rtd       DIR    8,3      4096       2 / find    113339 vmware  txt       REG    8,3    203296 1180356 /usr/bin/find find    113339 vmware  mem       REG    8,3 106374736 1187939 /usr/lib/locale/locale-archive find    113339 vmware  mem       REG    8,3    141880 1191334 /usr/lib64/libpthread-2.20.so find    113339 vmware  mem       REG    8,3     19512 1190784 /usr/lib64/libdl-2.20.so find    113339 vmware  mem       REG    8,3    447240 1191294 /usr/lib64/libpcre.so.1.2.3 find    113339 vmware  mem       REG    8,3   2082456 1190695 /usr/lib64/libc-2.20.so find    113339 vmware  mem       REG    8,3   1167000 1191118 /usr/lib64/libm-2.20.so find    113339 vmware  mem       REG    8,3    154784 1191415 /usr/lib64/libselinux.so.1 find    113339 vmware  mem       REG    8,3    163184 1190512 /usr/lib64/ld-2.20.so find    113339 vmware  mem       REG    8,3     26254 1448972 /usr/lib64/gconv/gconv-modules.cache find    113339 vmware  mem       REG    8,3     30239 3015834 /usr/share/locale/zh_CN/LC_MESSAGES/findutils.mo find    113339 vmware    0u      CHR  136,0       0t0       3 /dev/pts/0 find    113339 vmware    1u      CHR  136,0       0t0       3 /dev/pts/0 find    113339 vmware    2u      CHR  136,0       0t0       3 /dev/pts/0 find    113339 vmware    3r      DIR    8,5      4096 2095005 /home/vmware/code/apue/02.chapter find    113339 vmware    4r  unknown                          /proc/113339/fd/4 (readlink: File name too long) find    113339 vmware    6r  unknown                          /proc/113339/fd/6 (readlink: File name too long) find    113339 vmware    7r  unknown                          /proc/113339/fd/7 (readlink: File name too long) find    113339 vmware    9r  unknown                          /proc/113339/fd/9 (readlink: File name too long) find    113339 vmware   10r  unknown                          /proc/113339/fd/10 (readlink: File name too long) find    113339 vmware   11r  unknown                          /proc/113339/fd/11 (readlink: File name too long)

 

出人意料的是并没有很多打开中的文件句柄。按我的理解,每遍历一层目录应该有一个目录文件的句柄被打开,但是现在看没有,是因为我造的例子比较特殊,每个目录下只有一个子目录?还是 find 另辟蹊径不用占用许多句柄?暂时不得而知。总的来讲,find 的表现要好于 ls,顿时对这个神奇的命令产生了敬仰。最后插一句题外话,从上面的输出我们可以看到另一个现象,就是因为路径太长了,readlink 返回了错误,可见对长路径,很多系统 api 也是不支持的。最后你可以使用 rm -rf xxxx 来尝试清理这些目录与文件:

[apue] Linux / Windows 系统上只能建立不超过 PATH_MAX / MAX_PATH 长度的路径吗?

 

不出所料 rm 占用了很多的内存和 CPU,不过好歹可以工作 (而且耗时没有 find 那么夸张,也就十几分钟),所以我的虚拟机可以恢复到测试前的工况。下面是 lsof 针对 rm 的一些输出

$ lsof -p `pidof rm` COMMAND   PID   USER   FD      TYPE DEVICE  SIZE/OFF    NODE NAME rm      70867 vmware  cwd       DIR    8,5      4096 2095005 /home/vmware/code/apue/02.chapter rm      70867 vmware  rtd       DIR    8,3      4096       2 / rm      70867 vmware  txt       REG    8,3     62872 1181241 /usr/bin/rm rm      70867 vmware  mem       REG    8,3 106374736 1187939 /usr/lib/locale/locale-archive rm      70867 vmware  mem       REG    8,3   2082456 1190695 /usr/lib64/libc-2.20.so rm      70867 vmware  mem       REG    8,3    163184 1190512 /usr/lib64/ld-2.20.so rm      70867 vmware    0u      CHR  136,0       0t0       3 /dev/pts/0 rm      70867 vmware    1u      CHR  136,0       0t0       3 /dev/pts/0 rm      70867 vmware    2u      CHR  136,0       0t0       3 /dev/pts/0 rm      70867 vmware    3u  unknown                          /proc/70867/fd/3 (readlink: File name too long) rm      70867 vmware    4u  unknown                          /proc/70867/fd/4 (readlink: No such file or directory) rm      70867 vmware    5u  unknown                          /proc/70867/fd/5 (readlink: File name too long) rm      70867 vmware    6u  unknown                          /proc/70867/fd/6 (readlink: File name too long) rm      70867 vmware    7u  unknown                          /proc/70867/fd/7 (readlink: File name too long) rm      70867 vmware    8u  unknown                          /proc/70867/fd/8 (readlink: File name too long)

 

和 find 一样,它没有多少打开中的文件句柄(否则打开文件句柄数早超限了)。另外从 lsof 的输出看,有一些节点已经被 rm 删除了,所以 readlink 报错。

结论

对超长的文件路径来说,不同的 Linux 命令的支持程度也是不同的,有的支持,有的不支持。而且考虑到传递给进程的命令行总长度也是有限制的,除了一些支持递归目录处理的命令外,普通的命令是不会支持这么长的路径的。另一方面,从程序员的角度考虑,对于大路径的支持也是比较麻烦的,首先是系统支不支持输入、输出超长路径;如果支持,输入的场景还比较好办,输出的场景就比较麻烦了。最简单的办法是自己定义一个大于 PATH_MAX 值的常量并使用它分配内存,但是这样也存在问题,一方面日常处理比较浪费内存;另一方面如果路径超过你自己定义的这个值,还是会出现接收截断的问题。而且程序员没有办法去预知要得到的路径长度,从而提前动态分配内存。

总结一下,这个最大路径限制并不是系统不能支持超长的路径,而且作为一种系统与应用之间的一个约定,有了这个约定之后,程序对路径的处理将得到简化。况且我们没有对超长路径的硬需求,绝大部分 Windows 应用在 260 个字符路径的限制下就跑得很好,Linux 4096 的限制就更不用说了。

这个测试程序的一个额外用处就是耗尽所在分区的 inode(?),并观察系统在这种极限情况下的一些表现,例如,当我试图截取屏幕时不能成功,得到下面的提示框:

[apue] Linux / Windows 系统上只能建立不超过 PATH_MAX / MAX_PATH 长度的路径吗?

 

 

当你需要验证程序在这种极限状态下的行为时,这个程序不失为一种有用工具。

[apue] Linux / Windows 系统上只能建立不超过 PATH_MAX / MAX_PATH 长度的路径吗?资料部分资料来自网络,侵权毕设源码联系删除

区块链毕设网(www.qklbishe.com)全网最靠谱的原创区块链毕设代做网站
部分资料来自网络,侵权联系删除!
资源收费仅为搬运整理打赏费用,用户自愿支付 !
qklbishe.com区块链毕设代做网专注|以太坊fabric-计算机|java|毕业设计|代做平台 » [apue] Linux / Windows 系统上只能建立不超过 PATH_MAX / MAX_PATH 长度的路径吗?资料

提供最优质的资源集合

立即查看 了解详情