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 结果、数组长度、qsort 的 nmemb/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() 函数参数。 |
关键补充说明
- 底层类型的“多样性”:同一类型别名在不同系统(如32位/64位Linux、FreeBSD)的底层类型可能不同(如
size_t在32位系统是unsigned int,64位是unsigned long),但使用别名可屏蔽差异,保证代码可移植。 - 头文件的“兼容性”:部分类型别名会在多个头文件中重复定义(如
pid_t也可能出现在<unistd.h>),实际开发中只需包含核心头文件(上表标注的“核心定义头文件”)即可。 - 无符号属性:
size_t、uid_t、gid_t等均为“无符号类型”,使用时避免与有符号类型(如int)混用,防止数值溢出或比较错误。
以下是 Unix/Linux 系统常用类型别名的代码示例 + 详细解释,覆盖所有类型的核心使用场景:
1. pid_t:进程 ID 类型
#include <stdio.h>
#include <unistd.h> // 包含 fork()、getpid()、getppid()
#include <sys/types.h>int main() {pid_t pid = fork(); // 用 pid_t 存储进程 IDif (pid < 0) {perror("fork 失败");return 1;} else if (pid == 0) {// 子进程:pid 为 0printf("子进程 PID = %d,父进程 PID = %d\n", getpid(), getppid()); // getpid() 返回当前进程 PID(pid_t 类型)} else {// 父进程:pid 为子进程 PIDprintf("父进程 PID = %d,子进程 PID = %d\n", getpid(), pid);}return 0;
}
解释:pid_t 用于标识进程,fork() 父进程返回子进程 PID,子进程返回 0,失败返回 -1。getpid()/getppid() 分别获取当前进程和父进程的 PID。
2. uid_t:用户 ID 类型
#include <stdio.h>
#include <unistd.h> // 包含 getuid()、getgid()
#include <sys/types.h>int main() {uid_t my_uid = getuid(); // 获取当前用户的 UIDgid_t my_gid = getgid(); // 获取当前用户组的 GIDprintf("当前用户 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 类型
#include <stdio.h>
#include <grp.h> // 包含 getgrgid()
#include <unistd.h>
#include <sys/types.h>int main() {gid_t my_gid = getgid(); // 获取当前用户组 GIDstruct 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:无符号长度/大小类型
#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:带符号长度/大小类型
#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_tif (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:文件偏移量类型
#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:文件权限/类型类型
#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 用于表示文件权限(如 0644、0755)和文件类型(如普通文件、目录)。open() 的第三个参数、chmod() 的参数均为 mode_t。
8. dev_t:设备 ID 类型
#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 号类型
#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:时间戳类型
#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 时钟周期类型
#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:文件描述符集合类型
#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:信号集合类型
#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 是操作集合的宏。
