Linux文件操作与进程 一、目录操作目录操作遵循“打开 → 读取 → 关闭”的流程类似于文件操作。1. 打开目录 (opendir)#include dirent.hDIR *opendir(const char *name);功能打开一个目录获取目录流指针。参数name目标目录的路径。返回值成功返回DIR*类型的目录流指针失败返回NULL。代码示例#include stdio.h #include dirent.h int main() { DIR *dir opendir(.); if (dir NULL) { perror(opendir); return 1; } printf(目录打开成功\n); closedir(dir); // 记得关闭 return 0; }2. 读取目录 (readdir)#include dirent.hstruct dirent *readdir(DIR *dirp);功能读取目录流中的下一个目录项。参数dirp已打开的目录流指针。返回值成功返回指向struct dirent的指针读到末尾或出错返回NULL。struct dirent核心成员ino_t d_ino文件的 inode 编号。unsigned char d_type文件类型如DT_REG常规文件DT_DIR目录。并非所有文件系统都支持。char d_name[]以\0结尾的文件名最大长度通常为 256。代码示例列出当前目录所有内容#include stdio.h #include dirent.h int main() { DIR *dir opendir(.); if (dir NULL) { perror(opendir); return 1; } struct dirent *entry; while ((entry readdir(dir)) ! NULL) { printf(%s (类型: %d)\n, entry-d_name, entry-d_type); } closedir(dir); return 0; }3. 关闭目录 (closedir)#include dirent.hint closedir(DIR *dirp);功能关闭目录流释放资源。参数dirp目录流指针。返回值成功返回0失败返回-1。⚠️ 注意使用完目录后务必调用此函数否则会造成资源泄露。4. 创建目录 (mkdir)#include sys/stat.hint mkdir(const char *pathname, mode_t mode);功能创建一个新目录。参数pathname目录路径。mode权限通常为八进制数如0777并受umask影响。返回值成功返回0失败返回-1。代码示例#include stdio.h #include sys/stat.h int main() { if (mkdir(new_folder, 0777) -1) { perror(mkdir); return 1; } printf(目录创建成功\n); return 0; } 补充umask会屏蔽掉mode中的某些权限位创建出的目录实际权限是mode ~umask。5. 获取当前工作目录 (getcwd)#include unistd.hchar *getcwd(char *buf, size_t size);功能获取当前进程的工作路径。参数buf存储路径的缓冲区地址。size缓冲区大小。返回值成功返回buf失败返回NULL。代码示例#include stdio.h #include unistd.h #include limits.h // PATH_MAX int main() { char cwd[PATH_MAX]; if (getcwd(cwd, sizeof(cwd)) ! NULL) { printf(当前工作目录: %s\n, cwd); } else { perror(getcwd); return 1; } return 0; }6. 切换工作目录 (chdir)#include unistd.hint chdir(const char *path);功能将进程的当前工作目录更改为path。参数path目标路径。返回值成功返回0失败返回-1。代码示例#include stdio.h #include unistd.h int main() { if (chdir(/tmp) 0) { char cwd[256]; getcwd(cwd, sizeof(cwd)); printf(已切换到: %s\n, cwd); } else { perror(chdir); } return 0; }二、时间相关函数处理日历时间、时间戳和格式化时间。1. 获取时间戳 (time)#include time.htime_t time(time_t *tloc);功能获取自 1970-01-01 00:00:00 UTC 到现在的秒数。参数若tloc非空时间戳也存入*tloc。返回值当前时间戳time_t类型。代码示例#include stdio.h #include time.h int main() { time_t ts time(NULL); // 常用传NULL的方式 printf(当前时间戳: %ld\n, (long)ts); return 0; }2. 时间戳转字符串 (ctime)#include time.hchar *ctime(const time_t *timep);功能将时间戳转换为像Wed Jun 30 21:49:08 2026\n的可读字符串。参数指向时间戳的指针。返回值指向静态内存的字符串指针不可重入。代码示例#include stdio.h #include time.h int main() { time_t ts time(NULL); printf(当前时间: %s, ctime(ts)); // 字符串自带换行 return 0; }3. 时间戳分解 (localtime)#include time.hstruct tm *localtime(const time_t *timep);功能将时间戳转换为本地时区的日历结构体。参数指向时间戳的指针。返回值指向struct tm的指针静态内存不可重入。struct tm成员tm_sec(0-60),tm_min(0-59),tm_hour(0-23)tm_mday(1-31),tm_mon(0-11, 0代表1月),tm_year(从1900起算需加1900)tm_wday(0-6, 周日为0),tm_yday(0-365)代码示例自定义格式化输出#include stdio.h #include time.h int main() { time_t ts time(NULL); struct tm *ptm localtime(ts); if (ptm) { printf(%d-%02d-%02d %02d:%02d:%02d\n, ptm-tm_year 1900, ptm-tm_mon 1, ptm-tm_mday, ptm-tm_hour, ptm-tm_min, ptm-tm_sec); } return 0; } 补充线程安全版本可用localtime_r。三、补充基础知识点1. 主函数传参int main(int argc, char *argv[])argc参数个数包括程序名本身。argv参数字符串数组argv[0]是程序名。代码示例#include stdio.h int main(int argc, char *argv[]) { printf(参数个数: %d\n, argc); for (int i 0; i argc; i) { printf(argv[%d] %s\n, i, argv[i]); } return 0; } // 运行./a.out hello world // 输出argc3, argv[0]./a.out, argv[1]hello, argv[2]world2.const修饰的指针const char *p指向的内容只读不能*p A可以p q。char * const p指针本身是只读可以*p A不能p q。const char * const p内容和指针均只读。 助记const在*左边修饰内容在*右边修饰指针本身。3. 普通文件分类文本文件 (ASCII)按字符编码存储如.c、.txt可以直接用文本编辑器查看。二进制文件按数据的内存原始格式存储如可执行文件、图片、数据库文件。通常读写速度更快占用空间更小。四、多任务并发 —— 进程进程是操作系统资源分配的最小单位拥有独立的 0~4G 虚拟地址空间用户空间栈、堆、数据区、文本区内核空间。1. 进程状态简介R(运行/就绪)正在运行或在队列中等待CPU。S(可中断睡眠)等待事件完成如 I/O 操作可被信号唤醒。D(不可中断睡眠)处理关键 I/O不响应任何信号。T(停止)收到SIGSTOP等信号暂停执行。Z(僵尸)进程已结束但父进程尚未回收其资源wait。X(结束)进程彻底销毁。2. 核心进程函数(1) 创建子进程 (fork)#include unistd.hpid_t fork(void);功能通过复制当前进程创建一个子进程。子进程会拷贝父进程的整个用户空间写时复制技术但不继承 PID。返回值执行一次返回两次。在父进程中返回子进程的 PID(0)在子进程中返回0失败返回 -1。代码示例#include stdio.h #include unistd.h int main() { pid_t pid fork(); if (pid 0) { perror(fork); return 1; } else if (pid 0) { // 子进程代码 printf(子进程: PID %d, 父PID %d\n, getpid(), getppid()); } else { // 父进程代码 printf(父进程: PID %d, 子进程PID %d\n, getpid(), pid); } return 0; } 补充fork()后父子进程的执行顺序由内核调度决定无法预知。(2) 获取进程ID (getpid,getppid)#include unistd.hpid_t getpid(void);// 获取当前进程PIDpid_t getppid(void);// 获取父进程PID(3) 进程退出 (exitvs_exit)#include stdlib.hvoid exit(int status);// C库函数会清理I/O缓冲、调用atexit注册函数#include unistd.hvoid _exit(int status);// 系统调用直接终止不清理代码示例观察缓冲区刷新#include stdio.h #include unistd.h #include stdlib.h int main() { printf(Hello); // 未换行数据在stdout缓冲区 // _exit(0); // 使用 _exit 可能看不到 Hello exit(0); // exit 会刷新缓冲区打印出 Hello return 0; // main 中的 return 等同于 exit }(4) 阻塞回收子进程 (wait)#include sys/wait.hpid_t wait(int *wstatus);功能阻塞父进程直到任意一个子进程结束回收其资源防止僵尸进程。参数wstatus存储子进程退出状态可为NULL。返回值成功返回结束的子进程 PID失败返回 -1。状态检查宏WIFEXITED(status)子进程是否正常退出 (exit/return)。真则用WEXITSTATUS(status)获取退出码 (0-255)。WIFSIGNALED(status)是否被信号杀死。真则用WTERMSIG(status)获取信号编号。代码示例#include stdio.h #include stdlib.h #include unistd.h #include sys/wait.h int main() { pid_t pid fork(); if (pid 0) { // 子进程 printf(子进程运行中...\n); sleep(2); exit(42); // 退出码为42 } else { // 父进程 int status; pid_t ret wait(status); if (ret 0) { if (WIFEXITED(status)) { printf(子进程 %d 正常退出状态码: %d\n, ret, WEXITSTATUS(status)); } else if (WIFSIGNALED(status)) { printf(子进程被信号 %d 终止\n, WTERMSIG(status)); } } } return 0; }(5) 指定回收子进程 (waitpid)#include sys/wait.hpid_t waitpid(pid_t pid, int *status, int options);功能更灵活地回收子进程。参数pid0等待指定 PID 的子进程。0等待与调用进程同一进程组的任意子进程。-1等待任意子进程同wait。-1等待进程组 ID 等于|pid|的任意子进程。options0默认阻塞。WNOHANG非阻塞若无子进程退出则立即返回 0。非阻塞轮询示例#include stdio.h #include unistd.h #include sys/wait.h int main() { pid_t pid fork(); if (pid 0) { sleep(5); return 0; } else { int status; pid_t ret; do { ret waitpid(pid, status, WNOHANG); if (ret 0) { printf(子进程仍在运行父进程可做其他事...\n); sleep(1); } } while (ret 0); if (ret pid) { printf(子进程 %d 已回收\n, pid); } } return 0; }3.exec函数族功能用新的程序镜像完全替换当前进程的文本段。调用成功不返回原程序的后续代码不会执行失败返回 -1。命名规则记忆l(list)命令行参数以arg0, arg1, ..., NULL变长列表传递。v(vector)参数以char* argv[]数组传递。p(path)会从PATH环境变量中搜索可执行文件带p的函数如execlp第一个参数只需给文件名。e(environment)可传递自定义环境变量数组。execl示例 (列表全路径)#include unistd.h #include stdio.h int main() { printf(准备执行 ls...\n); // 格式 execl(路径, 程序名(惯例), 参数1, 参数2, ..., NULL) if (execl(/bin/ls, ls, -l, /home, NULL) -1) { perror(execl); return 1; } // 下面的代码不会被执行 printf(这句话永远不会打印\n); return 0; }execlp示例 (列表仅文件名)#include unistd.h #include stdio.h int main() { printf(执行 date 命令...\n); execlp(date, date, NULL); perror(execlp); return 1; }execv示例 (数组全路径)#include unistd.h #include stdio.h int main() { char *args[] {ls, -l, -a, NULL}; printf(通过 execv 执行 ls...\n); execv(/bin/ls, args); perror(execv); return 1; }execvp示例 (数组文件名)#include unistd.h #include stdio.h int main() { char *args[] {cat, notes.txt, NULL}; execvp(cat, args); perror(execvp); return 1; }⚠️ 注意exec族函数常与fork配合使用。fork创建一个子进程子进程调用exec去执行另一个程序而父进程继续原来的工作。这是 Unix 创建新进程的标准模式。

相关新闻

最新新闻

PP-OCRv4_server_rec:以80.61%识别精度重新定义服务端OCR技术标准

PP-OCRv4_server_rec:以80.61%识别精度重新定义服务端OCR技术标准

PP-OCRv4_server_rec:以80.61%识别精度重新定义服务端OCR技术标准 【免费下载链接】PP-OCRv4_server_rec 项目地址: https://ai.gitcode.com/paddlepaddle/PP-OCRv4_server_rec PP-OCRv4_server_rec作为飞桨PaddleOCR团队推出的新一代文本行识别模型&#x…

2026/7/27 9:29:09
如何高效构建专业级输入仿真系统:5个实战场景解析

如何高效构建专业级输入仿真系统:5个实战场景解析

如何高效构建专业级输入仿真系统:5个实战场景解析 【免费下载链接】ViGEmBus Windows kernel-mode driver emulating well-known USB game controllers. 项目地址: https://gitcode.com/gh_mirrors/vi/ViGEmBus 在Windows游戏开发和输入设备集成领域&#xf…

2026/7/27 9:29:09
实战指南:掌握Simon J.D. Prince的深度学习系统

实战指南:掌握Simon J.D. Prince的深度学习系统

实战指南:掌握Simon J.D. Prince的深度学习系统 【免费下载链接】udlbook Understanding Deep Learning - Simon J.D. Prince 项目地址: https://gitcode.com/gh_mirrors/ud/udlbook 当你在实际项目中遇到神经网络训练不收敛、模型过拟合或注意力机制难以理解…

2026/7/27 9:29:09
Android触摸事件分发机制与实战优化

Android触摸事件分发机制与实战优化

1. Android触摸事件分发机制深度解析在Android应用开发中,触摸事件分发机制是每个开发者必须掌握的核心知识体系。我曾在多个复杂手势交互项目中踩过不少坑,今天就来系统梳理下从手指接触屏幕到事件最终处理的完整链路。理解这套机制的价值在于&#xff…

2026/7/27 9:29:09
解锁A8-A11设备的终极越狱指南:用palera1n让旧iPhone重获新生

解锁A8-A11设备的终极越狱指南:用palera1n让旧iPhone重获新生

解锁A8-A11设备的终极越狱指南:用palera1n让旧iPhone重获新生 【免费下载链接】palera1n Jailbreak for A8 through A11, T2 devices, on iOS/iPadOS/tvOS 15.0, bridgeOS 5.0 and higher. 项目地址: https://gitcode.com/GitHub_Trending/pa/palera1n 还在为…

2026/7/27 9:29:09
如何用FunASR构建智能语音识别系统:从个人应用到企业部署的完整指南

如何用FunASR构建智能语音识别系统:从个人应用到企业部署的完整指南

如何用FunASR构建智能语音识别系统:从个人应用到企业部署的完整指南 【免费下载链接】FunASR Open-source speech recognition toolkit for training, inference, streaming ASR, VAD, punctuation, speaker diarization pipelines, and OpenAI-compatible/MCP serv…

2026/7/27 9:24:08

月新闻