题目是:
4.11 4.21节中的myftw从不改变其目录,对这种处理方法进行改动:每次遇到一个目录就用其调用chdir,这样每次调用lstat时,就可以使用文件名而非绝对文件名,处理完所有目录后再调用chdir(".."),比较这两种的运行时间。
使用chdir的时间是:1003192 us
不使用chdir的时间是:time: 2291574 us
明显是使用了chdir会快一倍
但是,为什么会快一倍,有人知道合理的解释吗?
以下是这两个程序的源代码
ftw8: 使用绝对路径的
#include "apue.h" #include <dirent.h> #include <limits.h> #include <sys/time.h> typedef int Myfunc(const char *, const struct stat *, int); static Myfunc myfunc; static int myftw(char *k, Myfunc *); static int dopath(Myfunc *); static long nreg, ndir, nblk, nchr, nfifo, nslink, nsock, ntot; int main(int argc, char *argv[]) { struct timeval start, end; int ret; int timeuse; if (argc != 2) err_quit("usage: ftw <starting-pathname>"); gettimeofday( &start, NULL ); ret = myftw(argv[1], myfunc); ntot = nreg + ndir + nblk + nchr + nfifo + nslink + nsock; if (ntot == 0) ntot = 1; printf("regular files = %7ld, %5.2f %%\n", nreg, nreg*100.0/ntot); printf("directories = %7ld, %5.2f %%\n", ndir, ndir*100.0/ntot); printf("block special = %7ld, %5.2f %%\n", nblk, nblk*100.0/ntot); printf("char special = %7ld, %5.2f %%\n", nchr, nchr*100.0/ntot); printf("FIFOs = %7ld, %5.2f %%\n", nfifo, nfifo*100.0/ntot); printf("symbolic links = %7ld, %5.2f %%\n", nslink, nslink*100.0/ntot); printf("sockets = %7ld, %5.2f %%\n", nsock, nsock*100.0/ntot); gettimeofday( &end, NULL ); timeuse = 1000000 * ( end.tv_sec - start.tv_sec ) + end.tv_usec -start.tv_usec; printf("time: %d us\n", timeuse); exit(ret); } #define FTW_F 1 #define FTW_D 2 #define FTW_DNR 3 #define FTW_NS 4 static char *fullpath; static size_t pathlen; static int myftw(char *pathname, Myfunc *func) { fullpath = path_alloc((&pathlen)); if (pathlen <= strlen(pathname)) { pathlen = strlen(pathname) * 2; if ((fullpath = realloc(fullpath, pathlen)) == NULL) err_sys("realloc failed"); } strcpy(fullpath, pathname); return(dopath(func)); } static int dopath(Myfunc *func) { struct stat statbuf; struct dirent *dirp; DIR *dp; int ret, n; if (lstat(fullpath, &statbuf) < 0) return(func(fullpath, &statbuf, FTW_NS)); if (S_ISDIR(statbuf.st_mode) == 0) return(func(fullpath, &statbuf, FTW_F)); if ((ret = func(fullpath, &statbuf, FTW_D)) != 0) return(ret); n = strlen(fullpath); if (n + NAME_MAX + 2 > pathlen) { pathlen *= 2; if ((fullpath = realloc(fullpath, pathlen)) == NULL) err_sys("realloc failed"); } fullpath[n++] = ‘/‘; fullpath[n] = 0; if ((dp = opendir(fullpath)) == NULL) return(func(fullpath, &statbuf, FTW_DNR)); while ((dirp = readdir(dp)) != NULL) { if (strcmp(dirp->d_name, ".") == 0 || strcmp(dirp->d_name, "..") == 0) continue; strcpy(&fullpath[n], dirp->d_name); printf("%s\n",fullpath); if ((ret = dopath(func)) != 0) break; } if (closedir(dp) < 0) err_ret("can‘t close directory %s", fullpath); return(ret); } static int myfunc(const char *pathname, const struct stat *statptr, int type) { switch (type) { case FTW_F: switch (statptr->st_mode & S_IFMT) { case S_IFREG: nreg++; break; case S_IFBLK: nblk++; break; case S_IFCHR: nchr++; break; case S_IFIFO: nfifo++; break; case S_IFLNK: nslink++; break; case S_IFSOCK: nsock++; break; case S_IFDIR: err_dump("for S_IFDIR for %s", pathname); } break; case FTW_D: ndir++; break; case FTW_DNR: err_ret("can‘t read directory %s", pathname); case FTW_NS: err_ret("stat error for %s", pathname); break; default: err_dump("unknown type %d for pathname %s", type, pathname); } return(0); }
e_4_11.c 使用chdir的
#include "apue.h" #include <dirent.h> #include <limits.h> #include <sys/time.h> typedef int Myfunc(const char *, const struct stat *, int); static Myfunc myfunc; static int myftw(char *k, Myfunc *); static int dopath(Myfunc *); static long nreg, ndir, nblk, nchr, nfifo, nslink, nsock, ntot; int main(int argc, char *argv[]) { struct timeval start, end; int ret; int timeuse; if (argc != 2) err_quit("usage: ftw <starting-pathname>"); gettimeofday( &start, NULL ); ret = myftw(argv[1], myfunc); ntot = nreg + ndir + nblk + nchr + nfifo + nslink + nsock; if (ntot == 0) ntot = 1; printf("regular files = %7ld, %5.2f %%\n", nreg, nreg*100.0/ntot); printf("directories = %7ld, %5.2f %%\n", ndir, ndir*100.0/ntot); printf("block special = %7ld, %5.2f %%\n", nblk, nblk*100.0/ntot); printf("char special = %7ld, %5.2f %%\n", nchr, nchr*100.0/ntot); printf("FIFOs = %7ld, %5.2f %%\n", nfifo, nfifo*100.0/ntot); printf("symbolic links = %7ld, %5.2f %%\n", nslink, nslink*100.0/ntot); printf("sockets = %7ld, %5.2f %%\n", nsock, nsock*100.0/ntot); gettimeofday( &end, NULL ); timeuse = 1000000 * ( end.tv_sec - start.tv_sec ) + end.tv_usec -start.tv_usec; printf("time: %d us\n", timeuse); exit(ret); } #define FTW_F 1 #define FTW_D 2 #define FTW_DNR 3 #define FTW_NS 4 static char *fullpath; static size_t pathlen; static int myftw(char *pathname, Myfunc *func) { fullpath = path_alloc((&pathlen)); if (pathlen <= strlen(pathname)) { pathlen = strlen(pathname) * 2; if ((fullpath = realloc(fullpath, pathlen)) == NULL) err_sys("realloc failed"); } strcpy(fullpath, pathname); return(dopath(func)); } static int dopath(Myfunc *func) { struct stat statbuf; struct dirent *dirp; DIR *dp; int ret, n; char *tmp; if (lstat(fullpath, &statbuf) < 0) return(func(fullpath, &statbuf, FTW_NS)); if (S_ISDIR(statbuf.st_mode) == 0) return(func(fullpath, &statbuf, FTW_F)); if ((ret = func(fullpath, &statbuf, FTW_D)) != 0) return(ret); n = strlen(fullpath); if (n + NAME_MAX + 2 > pathlen) { pathlen *= 2; if ((fullpath = realloc(fullpath, pathlen)) == NULL) err_sys("realloc failed"); } fullpath[n++] = ‘/‘; fullpath[n] = 0; if (chdir(fullpath) < 0) err_quit("chdir error"); if ((dp = opendir(".")) == NULL) return(func(fullpath, &statbuf, FTW_DNR)); while ((dirp = readdir(dp)) != NULL) { if (strcmp(dirp->d_name, ".") == 0 || strcmp(dirp->d_name, "..") == 0) continue; strcpy(&fullpath[n], dirp->d_name); if ((tmp = (char *)malloc(strlen(fullpath)+1)) == NULL) err_quit("malloc error"); strcpy(tmp, fullpath); strcpy(fullpath, dirp->d_name); printf("%s\n",fullpath); if ((ret = dopath(func)) != 0) break; } if (closedir(dp) < 0) err_ret("can‘t close directory %s", fullpath); if (chdir("..") < 0) err_quit("chdir to .. error"); return(ret); } static int myfunc(const char *pathname, const struct stat *statptr, int type) { switch (type) { case FTW_F: switch (statptr->st_mode & S_IFMT) { case S_IFREG: nreg++; break; case S_IFBLK: nblk++; break; case S_IFCHR: nchr++; break; case S_IFIFO: nfifo++; break; case S_IFLNK: nslink++; break; case S_IFSOCK: nsock++; break; case S_IFDIR: err_dump("for S_IFDIR for %s", pathname); } break; case FTW_D: ndir++; break; case FTW_DNR: err_ret("can‘t read directory %s", pathname); case FTW_NS: err_ret("stat error for %s", pathname); break; default: err_dump("unknown type %d for pathname %s", type, pathname); } return(0); }
时间: 2024-10-11 04:31:44