活动介绍

UNIX编程实用工具与库函数详解

立即解锁
发布时间: 2025-08-22 01:29:22 阅读量: 1 订阅数: 7
PDF

UNIX系统编程:通信、并发与线程精解

### UNIX编程实用工具与库函数详解 #### 1. Makefiles的使用 Make工具允许用户增量式地重新编译一组程序模块,既方便又能避免错误。使用Make时,需要在描述文件中指定模块之间的依赖关系,Make工具会根据这个文件来判断是否有需要更新的内容。 描述文件指定了目标和其他组件之间的依赖关系,以 `#` 开头的行是注释。依赖关系的形式如下: ```plaintext target: components TAB rule ``` 第一行称为依赖项,第二行称为规则。描述文件中规则行的第一个字符必须是制表符(TAB)。一个依赖项后面可以跟一个或多个规则行。 默认的描述文件名是 `makefile` 和 `Makefile`。当用户不带额外参数输入 `make` 命令时,Make工具会在当前目录中查找 `makefile` 或 `Makefile` 作为描述文件。 以下是一些示例: - **示例A.16**:编译 `client.c` 程序,使用重启库、UICI库和UICI名称库,并使用 `getnameinfo` 和 `getaddrinfo` 函数。 ```bash cc -DREENTRANCY=REENTRANT_POSIX -o client client.c restart.c uiciname.c uici.c ``` 在某些系统上可能还需要额外的库。 - **示例A.17**:可执行文件 `mine` 依赖于目标文件 `mine.o` 和 `minelib.o`。 ```plaintext mine: mine.o minelib.o cc -o mine mine.o minelib.o ``` 这个依赖关系表明,如果 `mine.o` 或 `minelib.o` 自 `mine` 最后一次更改后被修改过,就会执行规则 `cc -o mine mine.o minelib.o` 来更新目标 `mine`。 - **示例A.18**:一个Makefile描述文件有三个目标。 ```plaintext my: my.o mylib.o cc -o my my.o mylib.o my.o: my.c myinc.h cc -c my.c mylib.o: mylib.c myinc.h cc -c mylib.c ``` 目标 `my` 依赖于目标 `my.o` 和 `mylib.o`。只需输入 `make` 命令即可完成所需的更新。 有时,用有向图来可视化描述文件的依赖关系会很有帮助。使用图节点(无重复)来表示目标和组件。如果目标A依赖于B,则从节点A向节点B绘制一条有向弧。一个合适的描述文件的图应该没有环。 描述文件还可以包含以下形式的宏定义: ```plaintext NAME = value ``` 当 `$(NAME)` 出现在描述文件中时,Make会在处理前将其替换为 `value`。宏定义中不要使用制表符。 #### 2. Make命令的使用技巧 - **指定目标**:Make命令允许在命令行中指定目标名称。在这种情况下,Make只会更新指定的目标。例如,以下命令会使Make只更新目标 `my`: ```bash make my ``` 这里的 `my` 被解释为默认描述文件(当前目录中的 `makefile` 或 `Makefile`)中的一个目标,而不是描述文件本身。 - **使用自定义描述文件**:如果描述文件的名称不是 `makefile` 或 `Makefile`,可以使用 `-f` 选项。例如,以下命令会从描述文件 `mymake` 中更新目标 `target1`: ```bash make -f mymake target1 ``` #### 3. 调试工具 ##### 3.1 lint工具 lint工具用于查找C源文件中的错误和不一致性。它会进行类型检查,尝试检测无法到达的语句,并指出可能浪费资源或不可移植的代码。lint还能检测各种常见错误,如使用 `=` 而不是 `==`,或在 `scanf` 参数中遗漏 `&`。 以下是一些使用示例: - **练习A.22**:在示例A.18的描述文件中添加以下行来对源文件进行lint检查: ```plaintext lintall: lint my.c mylib.c > my.lint ``` 输入 `make lintall` 命令对程序进行lint检查,lint的输出会保存在 `my.lint` 文件中。 - **练习A.23**:对以下lint消息的解释: ```plaintext implicitly declared to return int: (14) strtok ``` 这个lint消息警告程序在源文件的第14行使用 `strtok` 时没有包含与之关联的 `string.h` 头文件。由于缺乏相反的信息,编译器假设 `strtok` 返回 `int`,但实际上 `strtok` 返回 `char*`。缺少头文件可能会在执行时导致灾难性的结果。 - **练习A.24**:对以下lint消息的解释: ```plaintext (5) warning: variable may be used before set: p ``` 这个消息通常在程序在设置指针值之前使用该指针时出现,例如以下代码段: ```c char *p; scanf("%s", p); ``` 指针 `p` 没有指向合适的字符缓冲区。代码可能会编译通过,但程序在执行时可能会产生段错误。 ##### 3.2 调试器 调试器是用于监控和控制其他程序执行的运行时程序。在UNIX环境中常见的调试器有 `dbx`、`adb`、`sdb` 和 `debug`。 使用调试器的步骤如下: 1. 用 `-g` 选项编译程序。例如,编译 `my.c` 程序: ```bash cc -g -o my my.c ``` 2. 在 `dbx` 调试器下运行程序: ```bash dbx my ``` 调试器会给出以下提示: ```plaintext (dbx) ``` 可以输入 `help` 获取命令列表,输入 `run` 运行程序。使用 `stop` 设置停止点,在输入 `run` 之前输入 `trace` 可以在变量值改变时开启跟踪。 许多程序员,尤其是初学者,发现调试器对于解决指针问题很有用。一些调试器有图形用户界面,使用起来更方便。但标准调试器在并发环境中作用较小,因为进程交互或时间因素可能会改变程序的行为。线程调试器的使用也有限。调试器可以帮助找到特定的执行错误,但不能替代程序测试计划。对函数调用进行良好的错误捕获可能是最有价值的调试策略。 ##### 3.3 truss工具 对于运行时调试,如果系统支持,`truss` 命令很有用。它会生成一个特定进程运行时所进行的系统调用和传递的信号的跟踪信息。使用 `-f` 选项可以跟踪该进程所有子进程的调用。需要注意的是,`truss` 命令不是POSIX的一部分,并非所有系统都支持。 例如,假设系统上安装了一个名为 `dvips` 的程序,它会访问 `psfonts.map` 文件。你已经将 `psfonts.map` 的副本放在了主目录的 `bin` 子目录中,但运行程序时收到了 “unable to open file” 错误消息。可以尝试执行以下命令(从C shell): ```bash truss dvips -f t.dvi |& grep psfonts.map ``` `truss` 程序会运行命令 `dvips -f t.dvi`,`grep` 会显示包含 `psfonts.map` 的输出行。`|&` 参数会将 `truss` 的标准输出和标准错误都通过管道传递给 `grep` 的标准输入。输出可能如下所示: ```plaintext open("./psfonts.map", O_RDONLY, 0666) Err#2 ENOENT open("/usr/local/tex/dvips/psfonts.map", O_RDONLY, 0666) Err#2 ENOENT ``` 这表明程序首先在当前目录中查找 `psfonts.map`,然后在 `/usr/local/tex/dvips` 目录中查找。将 `psfonts.map` 复制到 `/usr/local/tex/dvips` 目录中,问题应该就可以解决。 ##### 3.4 性能分析工具 大多数C编译器都有用于分析程序性能的选项。性能分析工具可以收集基本块的执行时间和函数调用频率等统计信息。可以查阅 `prof`、`gprof`、`monitor`、`profil` 和 `tcov` 以及 `cc` 的手册页以获取更多关于性能分析的信息。 #### 4. 标识符、存储类和链接类 程序员常常对关键字 `static` 的含义感到困惑,部分原因是C语言以两种不同的方式使用这个词。主要需要记住以下几点: | static是否应用 | 声明位置 | static修改的内容 | 存储类 | 链接类 | | ---- | ---- | ---- | ---- | ---- | | 是 | 块内 | 存储类 | 静态 | 无 | | 否 | 块内 | 存储类 | 自动 | 无 | | 是 | 块外 | 链接类 | 静态 | 内部 | | 否 | 块外 | 链接类 | 静态 | 外部 | - **应用于函数**:如果 `static` 应用于一个函数,那么该函数只能从定义它的文件中调用。 - **变量定义在块外**:变量在程序的整个生命周期内都存在。如果应用了 `static`,该变量只能从包含其定义的文件中访问;否则,该变量可以在程序的任何地方访问。 - **变量定义在块内**:变量只能在块内访问。如果应用了 `static`,变量在程序的整个生命周期内都存在,并且在执行离开块时保留其值;否则,变量在进入块时创建,在执行离开块时销毁,并且在使用前需要显式初始化。 这些规则基于C语言中标识符的作用域和链接的概念。根据ISO C标准,“标识符可以表示对象、函数、结构体、联合体或枚举的标签或成员、typedef名称、标签名称、宏名称或宏参数”。这里主要讨论与变量和函数相关的标识符。 标识符只能在称为其作用域的程序文本区域内使用。如果两个不同的实体由同一个标识符表示,它们的作用域必须不相交,或者一个作用域必须完全包含在另一个作用域内。在内部作用域中,另一个实体被隐藏,不能通过该标识符引用。 作用域从标识符声明开始。如果声明发生在块内,标识符具有块作用域,作用域在块结束时结束;如果声明发生在任何块之外,标识符具有文件作用域,作用域在声明它的文件结束时结束。 由于链接的原因,多次声明的标识符可能引用同一个对象。每个标识符都有外部、内部或无三种链接类。程序中具有外部链接的特定标识符的声明引用同一个实体;文件中具有内部链接的特定标识符的声明表示同一个实体;每个具有无链接的标识符声明表示一个唯一的实体。 函数标识符默认具有外部链接,这意味着它可以在程序的任何文件中被引用。在定义它的文件之外引用它需要函数原型。可以使用 `static` 限定符将函数的链接类设置为内部,从而使其对其他文件不可见。 对象(如变量)的标识符的链接类与其存储类(也称为存储时长)相关。存储时长决定了对象的生命周期,即程序执行过程中保证为对象保留存储的部分。有三种存储时长:静态、自动和动态分配。 动态分配的对象的生命周期从成功调用 `malloc` 或相关函数开始,到对象被显式释放或程序终止时结束。其他对象的生命周期由相应标识符的声明决定。 在任何块之外声明的对象的标识符具有静态存储类。具有静态存储类的对象在程序的整个生命周期内都存在,它们只初始化一次,并保留其最后存储的值。如果声明中没有显式初始化,它们将被初始化为0。与函数一样,这些标识符默认具有外部链接,但可以使用 `static` 限定符将其链接类设置为内部。 在块内声明的对象的标识符没有链接,每个标识符表示一个唯一的对象。这些标识符默认具有自动存储时长。具有自动存储类的对象在进入块时创建,在执行离开块时销毁。这些对象默认不初始化,并且在执行离开块后不一定保留其最后存储的值。如果通过递归或多线程进入块,每次进入块都会创建一个不同的对象。具有自动存储类的变量称为自动变量。 在块内声明的对象的标识符可以使用 `static` 限定符设置为静态存储时长。这样,对象在程序的整个生命周期内都存在,并保留其最后存储的值。如果通过递归或多线程进入块,将使用同一个对象。 具有静态存储时长标识符的对象通常称为静态变量,具有自动存储时长标识符的对象称为自动变量。 #### 5. 重启库 重启库是一组函数,当它们由于可能的临时事件而未完成时会自动重启。该库主要处理两种类型的事件:信号中断和不完整的I/O。 例如,许多库函数(如 `read` 和 `write`)在被信号中断且尚未进行任何I/O操作时会返回 `-1` 并将 `errno` 设置为 `EINTR`,这并不是真正的错误,而是程序在处理阻塞I/O时处理信号时发生的自然事件。当这些函数返回 `-1` 且 `errno` 设置为 `EINTR` 时,库函数会重启。 一些函数(如 `write`)可能在满足完整请求之前返回。当请求写入 `n` 字节时,只要写入的字节数大于零,`write` 调用就被认为是成功的。如果在写入请求的字节数之前捕获到信号,或者I/O缓冲区已满(如写入管道或网络连接时),`write` 函数可能会返回一个小于 `n` 的正值。通常,程序必须处理这种情况并写入剩余的字节。重启库中的函数通过写入剩余字节来简化用户代码。 以下是重启库中函数的完整列表: | 原型 | 描述 | | ---- | ---- | | `int r_close(int fildes)` | 类似于 `close` | | `int r_dup2(int fildes, int fildes2)` | 类似于 `dup2` | | `int r_open2(const char *path, int oflag)` | 类似于使用两个参数调用 `open` | | `int r_open3(const char *path, int oflag, mode_t mode)` | 类似于使用三个参数调用 `open` | | `ssize_t r_read(int fd, void *buf, size_t size)` | 类似于 `read` | | `pid_t r_wait(int *stat_loc)` | 类似于 `wait` | | `pid_t r_waitpid(pid_t pid, int *stat_loc, int options)` | 类似于 `waitpid` | | `ssize_t r_write(int fd, void *buf, size_t size)` | 类似于 `write`,但如果写入的字节数少于 `size` 会重启(可能的返回值只有 `size` 和 `-1`) | | `struct timeval add2currenttime(double seconds)` | 返回一个 `struct timeval` 结构,对应于当前时间加上 `seconds` 秒 | | `int copyfile(int fromfd, int tofd)` | 将字节从一个打开的文件描述符复制到另一个文件描述符,直到文件结束或出现错误 | | `ssiz
corwn 最低0.47元/天 解锁专栏
赠100次下载
继续阅读 点击查看下一篇
profit 400次 会员资源下载次数
profit 300万+ 优质博客文章
profit 1000万+ 优质下载资源
profit 1000万+ 优质文库回答
复制全文

相关推荐

吴雄辉

高级架构师
10年武汉大学硕士,操作系统领域资深技术专家,职业生涯早期在一家知名互联网公司,担任操作系统工程师的职位负责操作系统的设计、优化和维护工作;后加入了一家全球知名的科技巨头,担任高级操作系统架构师的职位,负责设计和开发新一代操作系统;如今为一名独立顾问,为多家公司提供操作系统方面的咨询服务。
最低0.47元/天 解锁专栏
赠100次下载
百万级 高质量VIP文章无限畅学
千万级 优质资源任意下载
千万级 优质文库回答免费看
立即解锁

专栏目录

最新推荐

FUNGuild与微生物群落功能研究:深入探索与应用

![FUNGuild与微生物群落功能研究:深入探索与应用](https://d3i71xaburhd42.cloudfront.net/91e6c08983f498bb10642437db68ae798a37dbe1/5-Figure1-1.png) # 摘要 FUNGuild作为一个先进的微生物群落功能分类工具,已在多个领域展示了其在分析和解释微生物数据方面的强大能力。本文介绍了FUNGuild的理论基础及其在微生物群落分析中的应用,涉及从数据获取、预处理到功能群鉴定及分类的全流程。同时,本文探讨了FUNGuild在不同环境(土壤、水体、人体)研究中的案例研究,以及其在科研和工业领域中的创

内存管理最佳实践

![内存管理最佳实践](https://img-blog.csdnimg.cn/30cd80b8841d412aaec6a69d284a61aa.png) # 摘要 本文详细探讨了内存管理的理论基础和操作系统层面的内存管理策略,包括分页、分段技术,虚拟内存的管理以及内存分配和回收机制。文章进一步分析了内存泄漏问题,探讨了其成因、诊断方法以及内存性能监控工具和指标。在高级内存管理技术方面,本文介绍了缓存一致性、预取、写回策略以及内存压缩和去重技术。最后,本文通过服务器端和移动端的实践案例分析,提供了一系列优化内存管理的实际策略和方法,以期提高内存使用效率和系统性能。 # 关键字 内存管理;分

【FPGA信号完整性故障排除】:Zynq7045-2FFG900挑战与解决方案指南

![【FPGA信号完整性故障排除】:Zynq7045-2FFG900挑战与解决方案指南](https://www.protoexpress.com/wp-content/uploads/2024/04/Parallel-termination-_diff.-pair-1-1024x421.jpg) # 摘要 随着电子系统对性能要求的日益提高,FPGA信号完整性成为设计和实现高性能电子系统的关键。本文从FPGA信号完整性基础讲起,分析了Zynq7045-2FFG900在高速接口设计中面临的信号完整性挑战,包括信号反射、串扰、电源地线完整性和热效应等问题,并探讨了硬件设计因素如PCB布局和元件选

【进阶知识掌握】:MATLAB图像处理中的相位一致性技术精通

![相位一致性](https://connecthostproject.com/images/8psk_table_diag.png) # 摘要 MATLAB作为一种高效的图像处理工具,其在相位一致性技术实现方面发挥着重要作用。本文首先介绍MATLAB在图像处理中的基础应用,随后深入探讨相位一致性的理论基础,包括信号分析、定义、计算原理及其在视觉感知和计算机视觉任务中的应用。第三章重点阐述了如何在MATLAB中实现相位一致性算法,并提供了算法编写、调试和验证的实际操作指南。第四章对算法性能进行优化,并探讨相位一致性技术的扩展应用。最后,通过案例分析与实操经验分享,展示了相位一致性技术在实际图

【MATLAB词性标注统计分析】:数据探索与可视化秘籍

![【MATLAB词性标注统计分析】:数据探索与可视化秘籍](https://img-blog.csdnimg.cn/097532888a7d489e8b2423b88116c503.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzMzNjI4MQ==,size_16,color_FFFFFF,t_70) # 摘要 MATLAB作为一种强大的数学计算和可视化工具,其在词性标注和数据分析领域的应用越来越广泛。本文

高斯过程可视化:直观理解模型预测与不确定性分析

# 摘要 高斯过程(Gaussian Processes, GP)是一种强大的非参数贝叶斯模型,在机器学习和时间序列分析等领域有着广泛应用。本文系统地介绍了高斯过程的基本概念、数学原理、实现方法、可视化技术及应用实例分析。文章首先阐述了高斯过程的定义、性质和数学推导,然后详细说明了高斯过程训练过程中的关键步骤和预测机制,以及如何进行超参数调优。接着,本文探讨了高斯过程的可视化技术,包括展示预测结果的直观解释以及多维数据和不确定性的图形化展示。最后,本文分析了高斯过程在时间序列预测和机器学习中的具体应用,并展望了高斯过程未来的发展趋势和面临的挑战。本文旨在为高斯过程的学习者和研究者提供一份全面的

【VB.NET代码优化】:性能提升与维护性的艺术

![【VB.NET代码优化】:性能提升与维护性的艺术](https://www.dotnetcurry.com/images/csharp/garbage-collection/garbage-collection.png) # 摘要 本文深入探讨了VB.NET代码优化的必要性、目标、基本技巧、性能分析与调优、高级优化方法以及维护与重构等方面。首先明确了VB.NET代码优化的重要性和优化目标,随后介绍了代码重构、数据访问和异步编程的优化技巧。在性能分析与调优部分,本文着重讲解了分析器工具的使用、算法与数据结构的优化和字符串处理的优化方法。高级优化方法涉及运行时编译、内存管理、资源管理以及针对

五子棋网络通信协议:Vivado平台实现指南

![五子棋,五子棋开局6步必胜,Vivado](https://www.xilinx.com/content/dam/xilinx/imgs/products/vivado/vivado-ml/sythesis.png) # 摘要 本文旨在探讨五子棋网络通信协议的设计与实现,以及其在Vivado平台中的应用。首先,介绍了Vivado平台的基础知识,包括设计理念、支持的FPGA设备和设计流程。接着,对五子棋网络通信协议的需求进行了详细分析,并讨论了协议层的设计与技术选型,重点在于实现的实时性、可靠性和安全性。在硬件和软件设计部分,阐述了如何在FPGA上实现网络通信接口,以及协议栈和状态机的设计

用户故事与用例:数据库需求分析【实践技巧】大公开

![数据库实践项目需求分析文档.doc](https://desarrolloweb.dlsi.ua.es/desarrollo-aplicaciones-web-19-20/practicas/08/acceso-recordatorio.png) # 摘要 用户故事与用例是现代软件需求工程中用于明确和描述需求的重要方法。本文首先概述了用户故事与用例的定义、价值及其在需求分析中的应用,并深入探讨了数据库需求分析的理论基础,包括数据完整性和一致性、高效查询和事务处理等核心原则。在实践案例分析章节中,文章通过案例研究展示了用户故事在实际项目中的应用以及用例在数据库设计中的实现,并讨论了如何将用

【紧急行动】:Excel文件损坏,.dll与.zip的终极解决方案

![【紧急行动】:Excel文件损坏,.dll与.zip的终极解决方案](https://img-blog.csdnimg.cn/direct/f7dfbf65d64a4d9abc605a79417e516f.png) # 摘要 本文针对Excel文件损坏的成因、机制以及恢复策略进行了全面的研究。首先分析了Excel文件的物理与逻辑结构,探讨了.dll文件的作用与损坏原因,以及.zip压缩技术与Excel文件损坏的关联。接着,介绍了.dll文件损坏的诊断方法和修复工具,以及在损坏后采取的应急措施。文中还详细讨论了Excel文件损坏的快速检测方法、从.zip角度的处理方式和手动修复Excel文