资讯动态

c实现fastdu替代du -sh ./* -c命令

发布时间:2026/9/29 21:23:44 来源:尧图企业网站定制
编辑命令gcc -O2 -pthread -stdc11 -o fastdu fastdu.c运行命令./fastdu # 用当前系统 CPU 核数个线程./fastdu -j 16 # 手动指定 16 线程#define _GNU_SOURCE #include stdio.h #include stdlib.h #include string.h #include dirent.h #include sys/stat.h #include unistd.h #include pthread.h typedef struct { char *path; int root; } task_t; static struct { task_t *buf; int cap, head, count; int active; /* 已弹出但未完成的任务数 */ pthread_mutex_t mtx; pthread_cond_t cond; } Q; static long long *root_sizes; static void queue_init(int cap) { Q.cap cap 0 ? cap : 64; Q.buf malloc(sizeof(task_t) * Q.cap); Q.head Q.count Q.active 0; pthread_mutex_init(Q.mtx, NULL); pthread_cond_init(Q.cond, NULL); } /* 取任务返回 0 表示全部完成 */ static int queue_pop(task_t *out) { pthread_mutex_lock(Q.mtx); while (Q.head Q.count Q.active 0) pthread_cond_wait(Q.cond, Q.mtx); if (Q.head Q.count) { pthread_mutex_unlock(Q.mtx); return 0; } *out Q.buf[Q.head]; if (Q.head Q.count) Q.head Q.count 0; /* 顺带回收数组头部 */ Q.active; pthread_mutex_unlock(Q.mtx); return 1; } static void queue_push(char *path, int root) { /* 接管 path 所有权 */ pthread_mutex_lock(Q.mtx); if (Q.count Q.cap) { if (Q.head 0) { /* 先压缩再扩容 */ int n Q.count - Q.head; memmove(Q.buf, Q.buf Q.head, sizeof(task_t) * n); Q.head 0; Q.count n; } if (Q.count Q.cap) { Q.cap * 2; Q.buf realloc(Q.buf, sizeof(task_t) * Q.cap); } } Q.buf[Q.count].path path; Q.buf[Q.count].root root; Q.count; pthread_cond_signal(Q.cond); pthread_mutex_unlock(Q.mtx); } static void queue_done(void) { pthread_mutex_lock(Q.mtx); Q.active--; if (Q.active 0 Q.head Q.count) pthread_cond_broadcast(Q.cond); pthread_mutex_unlock(Q.mtx); } static inline void add_size(int root, long long sz) { __atomic_fetch_add(root_sizes[root], sz, __ATOMIC_RELAXED); } static void *worker(void *arg) { (void)arg; task_t t; while (queue_pop(t)) { DIR *d opendir(t.path); if (d) { size_t plen strlen(t.path); struct dirent *e; while ((e readdir(d)) ! NULL) { const char *n e-d_name; if (n[0] . (n[1] \0 || (n[1] . n[2] \0))) continue; /* 跳过 . 和 .. */ size_t nlen strlen(n); char *full malloc(plen nlen 2); memcpy(full, t.path, plen); full[plen] /; memcpy(full plen 1, n, nlen 1); if (e-d_type DT_DIR) { queue_push(full, t.root); } else if (e-d_type DT_REG) { struct stat st; if (stat(full, st) 0) add_size(t.root, st.st_size); free(full); } else if (e-d_type DT_UNKNOWN) { struct stat st; /* 某些文件系统 d_type 无效 */ if (lstat(full, st) 0) { if (S_ISDIR(st.st_mode)) queue_push(full, t.root); else { add_size(t.root, st.st_size); free(full); } } else free(full); } else { free(full); /* 符号链接/fifo 等直接忽略 */ } } closedir(d); } free(t.path); queue_done(); } return NULL; } static void fmt_size(long long sz, char *buf, size_t buflen) { static const char *u[] {, K, M, G, T, P}; double v (double)sz; int i 0; while (v 1024.0 i 5) { v / 1024.0; i; } if (i 0) snprintf(buf, buflen, %lld, sz); else if (v 10.0) snprintf(buf, buflen, %.1f%s, v, u[i]); else snprintf(buf, buflen, %.0f%s, v, u[i]); } static int cmp_str(const void *a, const void *b) { return strcmp(*(char * const *)a, *(char * const *)b); } int main(int argc, char **argv) { int nthreads 0, opt; while ((opt getopt(argc, argv, j:)) ! -1) if (opt j) nthreads atoi(optarg); if (nthreads 0) { long n sysconf(_SC_NPROCESSORS_ONLN); nthreads (n 0) ? (int)n : 4; } if (nthreads 64) nthreads 64; DIR *d opendir(.); if (!d) { perror(opendir); return 1; } char **names NULL; int nn 0, cap 0; struct dirent *e; while ((e readdir(d)) ! NULL) { if (e-d_name[0] .) continue; /* 与 ./* 通配一致 */ if (cap nn) { cap cap ? cap * 2 : 64; names realloc(names, sizeof(char *) * cap); } names[nn] strdup(e-d_name); } closedir(d); qsort(names, nn, sizeof(char *), cmp_str); root_sizes calloc(nn 0 ? nn : 1, sizeof(long long)); queue_init(nn 0 ? nn : 64); for (int i 0; i nn; i) { size_t l strlen(names[i]) 3; char *p malloc(l); snprintf(p, l, ./%s, names[i]); struct stat st; if (lstat(p, st) 0) { if (S_ISDIR(st.st_mode)) { queue_push(p, i); continue; } add_size(i, st.st_size); /* 顶层普通文件 */ } free(p); } pthread_t *th malloc(sizeof(pthread_t) * nthreads); for (int i 0; i nthreads; i) pthread_create(th[i], NULL, worker, NULL); for (int i 0; i nthreads; i) pthread_join(th[i], NULL); long long total 0; char buf[32]; for (int i 0; i nn; i) { fmt_size(root_sizes[i], buf, sizeof buf); printf(%8s ./%s\n, buf, names[i]); total root_sizes[i]; } fmt_size(total, buf, sizeof buf); printf(%8s total\n, buf); return 0; }

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑