unistd.h在C语言中到底扮演什么角色?

99ANYc3cd6
预计阅读时长 17 分钟
位置: 首页 C语言 正文

什么是 unistd.h

unistd.h 是一个在 POSIX (Portable Operating System Interface) 标准中定义的头文件,POSIX 是一套为 Unix 和类 Unix 操作系统(如 Linux, macOS, BSD 等)设计的 API 规范。

c语言 unistd
(图片来源网络,侵删)

unistd.h 的名字来源于 "Unix Standard",它提供了一组标准的、与 Unix 系统调用相关的函数、宏和常量,这个头文件是 C 语言在 Unix-like 环境下进行底层编程的基石之一。

核心要点:

  • 平台相关: 它主要存在于 Unix-like 系统中,在 Windows 系统上,你找不到这个头文件(Windows 有自己的 API,如 windows.h)。
  • 提供系统调用接口: 它封装了操作系统内核提供的许多基本功能,如文件 I/O、进程控制、内存管理、用户信息等。

为什么需要 unistd.h

在 C 语言标准库(如 stdio.h)出现之前,程序与操作系统的交互直接通过系统调用完成。unistd.h 将这些系统调用封装成了更易于使用的 C 函数。

当你想从文件中读取数据时:

c语言 unistd
(图片来源网络,侵删)
  • 底层方式: 使用 read() 系统调用(由 unistd.h 提供)。
  • 高层方式: 使用 fread() 函数(由 stdio.h 提供)。

fread() 内部最终还是调用了 read(),但 fread 提供了缓冲机制,效率更高,接口更友好。unistd.h 提供的是更“原生”、更“底层”的访问方式。


unistd.h 中包含哪些常用内容?

unistd.h 内容非常丰富,这里列出一些最常用和最重要的函数和宏。

文件 I/O

  • int close(int fd);

    • 功能: 关闭一个文件描述符。fd 是一个非负整数,代表一个打开的文件、管道或套接字。
    • 示例: close(1); 会关闭标准输出。
  • ssize_t read(int fd, void *buf, size_t count);

    c语言 unistd
    (图片来源网络,侵删)
    • 功能: 从文件描述符 fd 中读取最多 count 个字节到缓冲区 buf
    • 返回值: 成功返回读取的字节数(可能小于 count),到达文件尾返回 0,出错返回 -1。
  • ssize_t write(int fd, const void *buf, size_t count);

    • 功能: 从缓冲区 buf 中写入最多 count 个字节到文件描述符 fd
    • 返回值: 成功返回写入的字节数,出错返回 -1。
  • off_t lseek(int fd, off_t offset, int whence);

    • 功能: 移动文件指针的当前位置。
    • whence 可以是 SEEK_SET (从文件头开始), SEEK_CUR (从当前位置开始), SEEK_END (从文件尾开始)。
    • 返回值: 成功返回新的文件指针位置,出错返回 -1。

进程控制

  • pid_t fork(void);

    • 功能: 创建一个新进程(称为子进程),这是 Unix 系统中实现多进程的关键。
    • 返回值:
      • 在父进程中,返回子进程的 PID (Process ID)。
      • 在子进程中,返回 0。
      • 如果失败,返回 -1。
    • 示例: 经典的 "Hello, world!" 多进程程序。
  • pid_t getpid(void);

    • 功能: 获取当前进程的 PID。
  • pid_t getppid(void);

    • 功能: 获取当前父进程的 PID。
  • void _exit(int status);

    • 功能: 立即终止当前进程,并将 status 返回给父进程(通过 wait()waitpid() 捕获)。注意: _exit 不会执行标准 I/O 库的清理工作(如刷新缓冲区),而 exit() 会。
  • unsigned int sleep(unsigned int seconds);

    • 功能: 让当前进程挂起(休眠)至少 seconds 秒。
    • 返回值: 返回剩余的秒数(如果被信号中断),或者 0(如果休眠了完整的时间)。

目录和文件系统操作

  • int chdir(const char *path);

    • 功能: 更改当前工作目录到 path
    • 返回值: 成功返回 0,失败返回 -1。
  • char *getcwd(char *buf, size_t size);

    • 功能: 获取当前工作目录的绝对路径,并将其存入 buf 缓冲区。
    • 返回值: 成功返回 buf 指针,失败返回 NULL。

用户和用户组信息

  • uid_t getuid(void);

    • 功能: 获取当前进程的真实用户 ID。
  • uid_t geteuid(void);

    • 功能: 获取当前进程的有效用户 ID (Effective User ID),这通常与文件权限检查相关。
  • gid_t getgid(void);

    • 功能: 获取当前进程的真实组 ID。
  • gid_t getegid(void);

    • 功能: 获取当前进程的有效组 ID。

杂项

  • int access(const char *pathname, int mode);

    • 功能: 检查文件 pathname 的访问权限。
    • mode 可以是 R_OK (读), W_OK (写), X_OK (执行), F_OK (文件存在) 的组合。
    • 返回值: 如果有权限,返回 0;否则返回 -1。
  • int unlink(const char *pathname);

    • 功能: 删除一个文件或解除一个符号链接,注意,对于正在被进程使用的文件,它并不会真正释放磁盘空间,直到所有使用它的进程都关闭了它。
  • char *getenv(const char *name);

    • 功能: 获取名为 name 的环境变量的值。

一个简单的 C 语言示例

下面是一个使用 unistd.hfork(), getpid(), getppid(), write()_exit() 的经典示例。

#include <stdio.h>      // 为了 printf
#include <unistd.h>     // 为了 fork, getpid, getppid, write, _exit
#include <sys/wait.h>   // 为了 waitpid
int main() {
    pid_t pid;
    int status;
    printf("Parent process (PID: %d) is about to fork.\n", getpid());
    pid = fork();
    if (pid == -1) {
        // fork 失败
        perror("fork failed");
        return 1;
    }
    if (pid == 0) {
        // --- 子进程代码 ---
        printf("Child process (PID: %d) started. My parent is (PID: %d).\n", getpid(), getppid());
        // 使用 write 向标准输出 (文件描述符 1) 写入
        write(1, "Hello from the child process!\n", 30);
        // 子进程正常退出,状态码为 0
        _exit(0);
    } else {
        // --- 父进程代码 ---
        printf("Parent process (PID: %d) created a child with PID: %d.\n", getpid(), pid);
        // 父进程等待子进程结束
        waitpid(pid, &status, 0);
        if (WIFEXITED(status)) {
            printf("Parent: Child process %d exited with status %d.\n", pid, WEXITSTATUS(status));
        }
    }
    return 0;
}

编译和运行 (在 Linux 或 macOS 上):

gcc -o unistd_example unistd_example.c
./unistd_example

预期输出:

Parent process (PID: 1234) is about to fork.
Parent process (PID: 1234) created a child with PID: 1235.
Child process (PID: 1235) started. My parent is (PID: 1234).
Hello from the child process!
Parent: Child process 1235 exited with status 0.

(注意:PID 每次运行都会不同)


特性 描述
名称 unistd.h (Unix Standard)
标准 POSIX 标准
平台 Unix-like 系统 (Linux, macOS, BSD 等)
作用 提供对底层操作系统功能的访问,封装了系统调用。
重要性 是进行 Unix/Linux 系统编程、编写服务器、工具脚本等任务的基础。

当你需要直接与操作系统内核交互,或者进行性能要求极高的编程时,unistd.h 是你不可或缺的工具,对于大多数常规应用,标准 C 库(如 stdio.h, stdlib.h)已经足够,但了解 unistd.h 能让你更深入地理解程序是如何在 Unix 系统上运行的。

-- 展开阅读全文 --
头像
C语言如何实现padleft左填充函数?
« 上一篇 04-22
dede程序安装教程具体步骤是怎样的?
下一篇 » 04-22

相关文章

取消
微信二维码
支付宝二维码

目录[+]