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 类型
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 用于表示文件权限(如 0644、0755)和文件类型(如普通文件、目录)。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 是操作集合的宏。