5. Unix/Linux 系统常用类型别名清单

Unix/Linux 系统常用类型别名清单

以下是 Unix/Linux 系统编程中高频使用的"类型别名"(均为库定义,非 C 语言关键字),按"类型名-头文件-底层类型-用途"结构化整理,兼顾准确性和实用性:

类型名 核心定义头文件 常见底层类型 核心用途
pid_t <sys/types.h> int / long 表示进程 ID(Process ID)、父进程 ID(PPID),如 fork() 返回值、getpid() 返回值。
uid_t <sys/types.h> unsigned int 表示用户 ID(User ID),区分不同系统用户,如 getuid()(获取当前用户 ID)。
gid_t <sys/types.h> unsigned int 表示组 ID(Group ID),区分用户组,如 getgid()(获取当前用户组 ID)。
size_t <stddef.h> / <stdio.h> unsigned int / unsigned long 表示"大小/长度"(无符号),如 sizeof 结果、数组长度、qsortnmemb/size 参数。
ssize_t <sys/types.h> / <unistd.h> int / long 表示"带符号的大小/长度",用于返回"有效长度"或"错误码(-1)",如 read()/write() 返回值。
off_t <sys/types.h> / <unistd.h> long / long long 表示文件偏移量(File Offset),用于文件定位,如 lseek() 函数的偏移参数。
mode_t <sys/types.h> / <sys/stat.h> unsigned int 表示文件权限和类型,如 open() 函数的权限参数(0644 等)、stat() 结构体成员。
dev_t <sys/types.h> / <sys/stat.h> unsigned long 表示设备 ID(Device ID),区分存储设备(如硬盘、U盘),如 stat() 结构体的 st_dev
ino_t <sys/types.h> / <sys/stat.h> unsigned long 表示inode号(索引节点号),文件系统中唯一标识文件,如 stat() 结构体的 st_ino
time_t <time.h> / <sys/types.h> long / long long 表示时间戳(秒级),存储从1970-01-01 00:00:00 UTC到当前的秒数,如 time() 返回值。
clock_t <time.h> long 表示CPU时钟周期数,用于计算程序运行时间,如 clock() 函数返回值。
fd_set <sys/select.h> / <sys/time.h> 自定义结构体 用于 select() 函数的文件描述符集合,管理"待监听的文件描述符"(如socket、文件)。
sigset_t <signal.h> 自定义结构体 表示信号集合,用于信号屏蔽、等待等操作,如 sigprocmask()sigwait() 函数参数。

关键补充说明

  1. 底层类型的"多样性":同一类型别名在不同系统(如32位/64位Linux、FreeBSD)的底层类型可能不同(如 size_t 在32位系统是 unsigned int,64位是 unsigned long),但使用别名可屏蔽差异,保证代码可移植。
  2. 头文件的"兼容性":部分类型别名会在多个头文件中重复定义(如 pid_t 也可能出现在 <unistd.h>),实际开发中只需包含核心头文件(上表标注的"核心定义头文件")即可。
  3. 无符号属性:size_tuid_tgid_t 等均为"无符号类型",使用时避免与有符号类型(如 int)混用,防止数值溢出或比较错误。

以下是 Unix/Linux 系统常用类型别名的代码示例 + 详细解释,覆盖所有类型的核心使用场景:

1. pid_t:进程 ID 类型

c 复制代码
#include <stdio.h>
#include <unistd.h>   // 包含 fork()、getpid()、getppid()
#include <sys/types.h>

int main() {
    pid_t pid = fork();  // 用 pid_t 存储进程 ID
    if (pid < 0) {
        perror("fork 失败");
        return 1;
    } else if (pid == 0) {
        // 子进程:pid 为 0
        printf("子进程 PID = %d,父进程 PID = %d\n", 
               getpid(), getppid());  // getpid() 返回当前进程 PID(pid_t 类型)
    } else {
        // 父进程:pid 为子进程 PID
        printf("父进程 PID = %d,子进程 PID = %d\n", 
               getpid(), pid);
    }
    return 0;
}

解释pid_t 用于标识进程,fork() 父进程返回子进程 PID,子进程返回 0,失败返回 -1。getpid()/getppid() 分别获取当前进程和父进程的 PID。

2. uid_t:用户 ID 类型

c 复制代码
#include <stdio.h>
#include <unistd.h>   // 包含 getuid()、getgid()
#include <sys/types.h>

int main() {
    uid_t my_uid = getuid();   // 获取当前用户的 UID
    gid_t my_gid = getgid();   // 获取当前用户组的 GID
    printf("当前用户 UID = %u,用户组 GID = %u\n", my_uid, my_gid);

    // 示例:判断是否为 root 用户(root 的 UID 是 0)
    if (my_uid == 0) {
        printf("当前用户是 root\n");
    } else {
        printf("当前用户是普通用户\n");
    }
    return 0;
}

解释uid_t 表示用户唯一标识,getuid() 返回当前用户的 UID,root 用户的 UID 为 0。gid_t 同理,标识用户组。

3. gid_t:用户组 ID 类型

c 复制代码
#include <stdio.h>
#include <grp.h>      // 包含 getgrgid()
#include <unistd.h>
#include <sys/types.h>

int main() {
    gid_t my_gid = getgid();          // 获取当前用户组 GID
    struct group *grp = getgrgid(my_gid);  // 根据 GID 获取用户组信息
    printf("当前用户组 GID = %u,组名 = %s\n", my_gid, grp->gr_name);
    return 0;
}

解释gid_t 表示用户组唯一标识,getgid() 返回当前用户组的 GID,getgrgid() 可根据 GID 查询组名等信息。

4. size_t:无符号长度/大小类型

c 复制代码
#include <stdio.h>
#include <string.h>   // 包含 strlen()
#include <stddef.h>   // 包含 size_t 定义

int main() {
    char str[] = "Hello, Unix!";
    size_t len = strlen(str);  // strlen() 返回值为 size_t(无符号)
    printf("字符串长度 = %zu\n", len);  // 格式化输出用 %zu

    // 示例:数组遍历(size_t 用于索引,避免负数)
    int arr[] = {1, 2, 3, 4, 5};
    size_t arr_len = sizeof(arr) / sizeof(arr[0]);
    for (size_t i = 0; i < arr_len; i++) {
        printf("arr[%zu] = %d\n", i, arr[i]);
    }
    return 0;
}

解释size_t 是无符号整数,用于表示"长度、大小、索引"等非负数值,如 strlen() 返回字符串长度、数组遍历索引。格式化输出需用 %zu

5. ssize_t:带符号长度/大小类型

c 复制代码
#include <stdio.h>
#include <unistd.h>   // 包含 read()
#include <fcntl.h>    // 包含 open()
#include <sys/types.h>
#include <sys/stat.h>

int main() {
    int fd = open("test.txt", O_RDONLY);  // 打开文件,获取文件描述符
    if (fd == -1) {
        perror("open 失败");
        return 1;
    }

    char buf[100];
    ssize_t bytes_read = read(fd, buf, sizeof(buf));  // read() 返回 ssize_t
    if (bytes_read == -1) {
        perror("read 失败");
    } else {
        printf("读取到 %zd 字节数据:%.*s\n", bytes_read, (int)bytes_read, buf);
    }

    close(fd);
    return 0;
}

解释ssize_t 是带符号整数,用于表示"有效长度"或"错误码(-1)",如 read()/write() 返回实际读写的字节数,失败返回 -1。格式化输出用 %zd

6. off_t:文件偏移量类型

c 复制代码
#include <stdio.h>
#include <unistd.h>   // 包含 lseek()
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>

int main() {
    int fd = open("test.txt", O_RDWR | O_CREAT, 0644);
    if (fd == -1) {
        perror("open 失败");
        return 1;
    }

    // 移动文件偏移量到文件末尾(SEEK_END 表示末尾)
    off_t offset = lseek(fd, 0, SEEK_END);
    printf("文件当前偏移量 = %ld 字节(文件大小)\n", (long)offset);

    // 移动偏移量到文件开头,写入数据
    lseek(fd, 0, SEEK_SET);
    write(fd, "Hello, off_t!", 13);

    close(fd);
    return 0;
}

解释off_t 表示文件中的"位置偏移",lseek() 用于移动文件指针,实现随机读写。SEEK_SET(开头)、SEEK_CUR(当前位置)、SEEK_END(末尾)是常用偏移基准。

7. mode_t:文件权限/类型类型

c 复制代码
#include <stdio.h>
#include <sys/stat.h>  // 包含 open()、chmod()
#include <fcntl.h>

int main() {
    // 以 0644 权限创建文件(rwx 对应 0-7,0644 表示"用户读/写,组读,其他读")
    int fd = open("test.txt", O_CREAT | O_WRONLY, 0644);
    if (fd == -1) {
        perror("open 失败");
        return 1;
    }
    close(fd);

    // 修改文件权限为 0755(用户读/写/执行,组读/执行,其他读/执行)
    mode_t new_mode = 0755;
    if (chmod("test.txt", new_mode) == -1) {
        perror("chmod 失败");
        return 1;
    }
    printf("文件权限已修改为 0%o\n", new_mode);  // 八进制输出权限
    return 0;
}

解释mode_t 用于表示文件权限(如 06440755)和文件类型(如普通文件、目录)。open() 的第三个参数、chmod() 的参数均为 mode_t

8. dev_t:设备 ID 类型

c 复制代码
#include <stdio.h>
#include <sys/stat.h>  // 包含 stat()
#include <sys/types.h>

int main() {
    struct stat stat_buf;
    if (stat("/dev/sda1", &stat_buf) == -1) {  // 获取设备文件的 stat 信息
        perror("stat 失败");
        return 1;
    }

    dev_t dev_id = stat_buf.st_dev;  // 设备 ID(存储设备的唯一标识)
    printf("设备 ID = %lu\n", (unsigned long)dev_id);
    return 0;
}

解释dev_t 表示设备的唯一标识,通过 stat() 可获取文件/设备的 st_dev(设备 ID)和 st_rdev(特殊设备 ID,如块设备、字符设备)。

9. ino_t:inode 号类型

c 复制代码
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>

int main() {
    struct stat stat_buf;
    if (stat("test.txt", &stat_buf) == -1) {  // 获取文件的 stat 信息
        perror("stat 失败");
        return 1;
    }

    ino_t inode = stat_buf.st_ino;  // 文件的 inode 号(文件系统内唯一)
    printf("文件 inode 号 = %lu\n", (unsigned long)inode);
    return 0;
}

解释ino_t 表示文件的 inode 号,是文件系统中文件的唯一标识(同一文件系统内不重复)。通过 stat() 可获取文件的 st_ino

10. time_t:时间戳类型

c 复制代码
#include <stdio.h>
#include <time.h>     // 包含 time()、ctime()
#include <sys/types.h>

int main() {
    time_t now = time(NULL);  // 获取当前时间戳(从 1970-01-01 00:00:00 UTC 到现在的秒数)
    printf("当前时间戳 = %ld\n", (long)now);

    // 将时间戳转换为可读字符串
    char *time_str = ctime(&now);
    printf("可读时间 = %s", time_str);
    return 0;
}

解释time_t 存储秒级时间戳,time() 获取当前时间戳,ctime()/localtime() 可将其转换为可读时间格式。

11. clock_t:CPU 时钟周期类型

c 复制代码
#include <stdio.h>
#include <time.h>     // 包含 clock()
#include <unistd.h>   // 包含 sleep()

int main() {
    clock_t start = clock();  // 获取程序启动到现在的 CPU 时钟周期数
    sleep(1);  // 模拟耗时操作
    clock_t end = clock();

    // 计算程序运行的 CPU 时间(单位:秒,CLOCKS_PER_SEC 是每秒时钟周期数)
    double cpu_time = (double)(end - start) / CLOCKS_PER_SEC;
    printf("程序运行的 CPU 时间 = %f 秒\n", cpu_time);
    return 0;
}

解释clock_t 存储 CPU 时钟周期数,clock() 返回从程序启动到调用时的时钟周期数,结合 CLOCKS_PER_SEC 可计算程序运行的 CPU 时间。

12. fd_set:文件描述符集合类型

c 复制代码
#include <stdio.h>
#include <sys/select.h>  // 包含 fd_set、select()
#include <sys/time.h>
#include <unistd.h>
#include <fcntl.h>

int main() {
    int fd = open("test.txt", O_RDONLY);
    if (fd == -1) {
        perror("open 失败");
        return 1;
    }

    fd_set read_fds;      // 定义文件描述符集合
    FD_ZERO(&read_fds);   // 清空集合
    FD_SET(fd, &read_fds);  // 将 fd 加入集合

    struct timeval tv = {5, 0};  // 超时时间:5秒
    // 监听集合中的文件描述符是否可读
    int ret = select(fd + 1, &read_fds, NULL, NULL, &tv);
    if (ret == -1) {
        perror("select 失败");
    } else if (ret == 0) {
        printf("超时(5秒内无数据可读)\n");
    } else {
        if (FD_ISSET(fd, &read_fds)) {  // 判断 fd 是否在就绪集合中
            printf("文件描述符 %d 可读\n", fd);
        }
    }

    close(fd);
    return 0;
}

解释fd_set 是存储"文件描述符集合"的结构体,用于 select() 函数监听多个文件描述符的状态(可读、可写、异常)。FD_ZERO/FD_SET/FD_ISSET 是操作集合的宏。

13. sigset_t:信号集合类型

c 复制代码
#include <stdio.h>
#include <signal.h>    // 包含 sigset_t、sigprocmask()
#include <unistd.h>

void sig_handler(int signum) {
    printf("捕获到信号 %d\n", signum);
}

int main() {
    signal(SIGINT, sig_handler);  // 注册 SIGINT(Ctrl+C)的处理函数

    sigset_t sig_set;      // 定义信号集合
    sigemptyset(&sig_set); // 清空集合
    sigaddset(&sig_set, SIGINT);  // 将 SIGINT 加入集合

    // 阻塞 SIGINT 信号(暂时屏蔽)
    sigprocmask(SIG_BLOCK, &sig_set, NULL);
    printf("SIGINT 已阻塞,按 Ctrl+C 不会触发处理函数,5秒后解除阻塞\n");
    sleep(5);

    // 解除阻塞
    sigprocmask(SIG_UNBLOCK, &sig_set, NULL);
    printf("SIGINT 已解除阻塞,按 Ctrl+C 可触发处理函数\n");
    while (1) { sleep(1); }  // 保持程序运行
    return 0;
}

解释sigset_t 是存储"信号集合"的结构体,用于信号屏蔽(sigprocmask)、等待(sigwait)等操作。sigemptyset/sigaddset/sigdelset 是操作集合的宏。

相关推荐
爱吃橘的橘猫2 小时前
如何解决VMware虚拟机中Linux系统终端不显示ens33 inet IP地址的问题
linux·运维·服务器·虚拟机
梁正雄3 小时前
linux服务-Bonding网卡绑定工具
linux·运维·linux bonding·网卡绑定
云边有个稻草人3 小时前
Windows 里用 Linux 不卡顿?WSL + cpolar让跨系统开发变简单
linux·运维·服务器·cpolar
打不了嗝 ᥬ᭄3 小时前
【Linux】网络层协议
linux·网络·c++·网络协议·http
LXY_BUAA4 小时前
将linux操作系统装入U盘20251107
linux·运维·服务器
kaoa0004 小时前
Linux入门攻坚——53、drbd - Distribute Replicated Block Device,分布式复制块设备-2
linux·运维·服务器
落羽的落羽5 小时前
【C++】现代C++的新特性constexpr,及其在C++14、C++17、C++20中的进化
linux·c++·人工智能·学习·机器学习·c++20·c++40周年
RisunJan5 小时前
Linux命令-e2label命令(设置第二扩展文件系统的卷标)
linux·运维·服务器
Claire_ccat5 小时前
2025山西省网络安全职业技能大赛PWN方向题解
linux·安全·网络安全·pwn·栈溢出