Skip to content

unistd.h

注意事项

  • 可移植性:unistd.h 是 POSIX 标准的一部分,在 Windows 系统中不可用(虽然有类似的实现如 io.h)
  • 错误处理:大多数 unistd.h 函数在出错时返回 -1 并设置 errno
  • 头文件依赖:通常需要与其他头文件如 fcntl.h、sys/types.h 等一起使用
  • 权限问题:许多函数需要适当的权限才能执行特定操作

目录操作

getcwd

获取当前工作目录的绝对路径

cpp
/**
 * 参数
 *   buf 存储路径的缓冲区指针,若为NULL,则函数自动分配内存(需要手动释放)
 *   size 缓冲区大小,若路径长度大于size,会返回NULL,并设置errno  
 */
char *getcwd(char *buf, size_t size);

示例

cpp
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(void)
{

    char *cwd = getcwd(NULL, 0);
    if (cwd != NULL)
    {
        printf("cwd: %s\n", cwd);
        free(cwd);
    }
    else
    {
        perror("cwd error");
    }

    return 0;
}

运行结果

shell
$ gcc main.c -o main && ./main
/Users/tom/workspace

// 改变当前工作目录 int chdir(const char *path);

进程控制

fork

创建子进程

cpp
/**
 * 父进程返回子进程PID
 * 子进程返回0
 */
pid_t fork(void)

示例

cpp
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(void)
{

    pid_t pid = fork();
    if (pid == 0)
    {
        printf("child pid: %d\n", getpid());
    }
    else
    {
        printf("parent pid: %d\n", getpid());
        wait(NULL);
    }

    return 0;
}

运行结果

shell
$ gcc main.c -o main && ./main
parent pid: 56606
child pid: 56607

_exit

进程终止

cpp
void _exit(int status);

示例

cpp
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(int argc, char const *argv[])
{
    printf("before _exit\n");
    _exit(EXIT_SUCCESS);
    printf("after _exit\n");
    return 0;
}

运行结果

shell
% gcc main.c -o main && ./main
before _exit

% echo $?
0

管道操作

pipe

创建匿名管道

注意:匿名管道只能在有亲缘关系的进程间使用

cpp
/**
 * 参数
 *      pipefd 文件描述符
 *  成功返回0,失败返回-1
 */ 
int pipe(int pipefd[2]);

示例

cpp
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

#define READ_END 0
#define WRITE_END 1

int main(int argc, char const *argv[])
{
    // 定义文件描述符数组
    int fds[2];

    // 创建管道
    if (pipe(fds) == -1)
    {
        perror("pipe error");
        return -1;
    }

    pid_t pid = fork();
    if (pid == 0)
    {
        // 子进程—写入
        close(fds[READ_END]); // 关闭读端

        const char *msg = "Hello World!";

        // 写数据
        write(fds[WRITE_END], msg, strlen(msg) + 1);
        close(fds[WRITE_END]); // close write end
        exit(0);
    }
    else if (pid > 0)
    {
        // 父进程—读取
        close(fds[WRITE_END]); // 关闭写端

        char buffer[100];
        read(fds[READ_END], buffer, sizeof(buffer));
        printf("Received message: %s\n", buffer);
        close(fds[READ_END]); // close read end
        wait(NULL);
    }

    return 0;
}

运行结果

shell
% gcc main.c  -o main && ./main
Received message: Hello World!

文件操作

access

cpp
/**
 * 参数
 *   path 文件名
 *   mode 检查项
 * 成功返回0,失败返回-1,并设置errno
 */ 
int access(const char *path, int mode);

mode可选:

  • R_OK 读取权限
  • W_OK 写权限
  • X_OK 执行权限
  • F_OK 存在检查

示例

cpp
#include <stdio.h>
#include <unistd.h>

int main(int argc, char const *argv[])
{
    // 检查文件是否存在
    int ret = access("main.c", F_OK);
    printf("ret=%d\n", ret);

    return 0;
}

执行结果

shell
% gcc main.c  -o main && ./main
ret=0

read

从文件描述符读取数据

cpp
ssize_t read(int fd, void *buf, size_t count);

示例

cpp
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>

int main(int argc, char const *argv[])
{

    // 打开文件
    int fd = open("temp.txt", O_RDONLY);

    char buf[20];

    int n = read(fd, buf, sizeof(buf)); // 读取文件内容
    // 添加字符串结束符
    buf[n] = '\0';
    printf("buf=%s\n", buf);

    close(fd);

    return 0;
}

运行结果

shell
% cat temp.txt 
Hello, World!

% gcc main.c -o main && ./main
buf=Hello, World!

write

向文件描述符写入数据

cpp
ssize_t write(int fd, const void *buf, size_t count);

示例

cpp
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>

int main(int argc, char const *argv[])
{

    // 创建并打开文件
    int fd = open("temp.txt", O_CREAT | O_WRONLY);
    if (fd == -1)
    {
        perror("open file error");
        return -1;
    }

    write(fd, "Hello, World!\n", 14); // 向文件写入数据

    close(fd);

    return 0;
}

运行结果

shell
$ gcc main.c -o main && ./main

% cat temp.txt 
Hello, World!

lseek

移动文件指针

cpp
/**
 * 参数
 * whence:
 *   - SEEK_SET 设置偏移
 *   - SEEK_CUR
 *   - SEEK_END 文件尾部
 */
off_t lseek(int fd, off_t offset, int whence);

示例

cpp
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>

int main(int argc, char const *argv[])
{

    // 打开文件
    int fd = open("temp.txt", O_RDONLY);

    char buf[20];
    int n = read(fd, buf, sizeof(buf)); // 读取文件内容
    // 添加字符串结束符
    buf[n] = '\0';
    printf("buf=%s\n", buf);

    // 将文件偏移量重新定位到文件开头
    lseek(fd, 0, SEEK_SET);
    n = read(fd, buf, sizeof(buf)); // 再次读取文件内容
    buf[n] = '\0';
    printf("buf=%s\n", buf);

    close(fd);

    return 0;
}

运行结果

shell
 % gcc main.c -o main && ./main
buf=Hello, World!

buf=Hello, World!

// 创建符号链接 int symlink(const char *target, const char *linkpath);

// 读取符号链接 ssize_t readlink(const char *pathname, char *buf, size_t bufsiz);

系统信息

getuid

获取用户ID

cpp
uid_t getuid(void);

// 获取有效用户ID uid_t geteuid(void);

// 获取组ID gid_t getgid(void);

// 获取有效组ID gid_t getegid(void);

// 获取主机名 int gethostname(char *name, size_t len);

cpp

示例

cpp

运行结果

shell
$ gcc main.c -o main && ./main

时间延迟

sleep

暂停执行一段时间

cpp
/**
 * 单位: 秒
 */
unsigned int sleep(unsigned int seconds);

示例

cpp
#include "log.h"
#include <unistd.h>

int main()
{
    // 初始化日志器
    Logger *logger = logger_init("", LOG_TO_CONSOLE, LOG_DEBUG);

    logger_log(logger, LOG_DEBUG, "start");

    sleep(3); // 暂停3秒

    logger_log(logger, LOG_DEBUG, "end");

    // 销毁日志器
    logger_destroy(logger);

    return 0;
}

其中,log.h 为日志模块

运行结果

shell
% gcc main.c log.c -o main && ./main
[2025-08-28 08:22:05] [DEBUG] start
[2025-08-28 08:22:08] [DEBUG] end

不同延时函数的比较

函数精度可移植性信号处理推荐度
usleep微秒级 (已过时)类 Unix 系统可能被信号中断,需手动处理⭐☆☆☆☆
nanosleep纳秒级类 Unix 系统提供更明确的信号处理规范,可自动重试⭐⭐⭐⭐⭐
clock_nanosleep纳秒级类 Unix 系统可指定时钟源,稳定性更高⭐⭐⭐⭐☆
Sleep毫秒级Windows行为取决于系统⭐⭐⭐⭐☆ (Windows)

usleep(废弃)

更精确的暂停

cpp
/**
 * 微秒
 * 成功时返回 0
 * 如果被信号中断,则返回 -1,并设置 errno 为 EINTR
 * 1s = 1000000us
 */
int usleep(useconds_t usec);

示例

cpp
#include "log.h"
#include <unistd.h>

int main()
{
    // 初始化日志器
    Logger *logger = logger_init("", LOG_TO_CONSOLE, LOG_DEBUG);

    logger_log(logger, LOG_DEBUG, "start");

    usleep(3000000); // 暂停3秒 1000000

    logger_log(logger, LOG_DEBUG, "end");

    // 销毁日志器
    logger_destroy(logger);

    return 0;
}

运行结果

shell
% gcc main.c log.c -o main && ./main
[2025-08-28 08:25:35] [DEBUG] start
[2025-08-28 08:25:38] [DEBUG] end

文件描述符

// 复制文件描述符 int dup(int oldfd); int dup2(int oldfd, int newfd);

// 关闭文件描述符 int close(int fd);

dup2

cpp
int dup2(int oldfd, int newfd);