getcwd系统调用及示例

getcwd - 获取当前工作目录

getcwd - 获取当前工作目录

函数介绍

getcwd系统调用用于获取进程当前的工作目录路径。它返回一个以null结尾的字符串,表示当前目录的绝对路径名。

函数原型

1
2
3
4
#include <unistd.h>

char *getcwd(char *buf, size_t size);

功能

获取进程当前工作目录的绝对路径名。

参数

  • char *buf: 指向存储路径名的缓冲区

  • size_t size: 缓冲区大小(字节)

返回值

  • 成功时返回指向缓冲区的指针(buf)

失败时返回NULL,并设置errno:

  • EINVAL: size参数为0且buf非NULL

  • ERANGE: 缓冲区太小

  • ENOMEM: 内存不足

相似函数

  • chdir(): 改变当前工作目录

  • fchdir(): 通过文件描述符改变当前工作目录

示例代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <limits.h>

int main() {
char buffer&#91;PATH_MAX];
char *result;

printf("=== Getcwd函数示例 ===\n");

// 示例1: 基本的获取当前目录操作
printf("\n示例1: 基本的获取当前目录操作\n");

// 方法1: 使用预分配的缓冲区
result = getcwd(buffer, sizeof(buffer));
if (result != NULL) {
printf("当前工作目录: %s\n", buffer);
} else {
perror("获取当前目录失败");
}

// 方法2: 让系统分配内存(buf为NULL,size为0)
char *dynamic_buffer = getcwd(NULL, 0);
if (dynamic_buffer != NULL) {
printf("动态分配的当前目录: %s\n", dynamic_buffer);
free(dynamic_buffer); // 需要手动释放内存
} else {
perror("动态获取当前目录失败");
}

// 示例2: 缓冲区大小处理
printf("\n示例2: 缓冲区大小处理\n");

// 测试不同大小的缓冲区
size_t sizes&#91;] = {10, 50, 100, PATH_MAX};
for (int i = 0; i < 4; i++) {
char small_buffer&#91;1000]; // 足够大的缓冲区
printf("尝试使用大小为 %zu 的缓冲区: ", sizes&#91;i]);

result = getcwd(small_buffer, sizes&#91;i]);
if (result != NULL) {
printf("成功,目录长度: %zu 字节\n", strlen(small_buffer));
} else {
if (errno == ERANGE) {
printf("失败 - 缓冲区太小\n");
} else {
printf("失败 - %s\n", strerror(errno));
}
}
}

// 示例3: 创建测试目录并切换
printf("\n示例3: 目录切换演示\n");

// 保存原始目录
char original_dir&#91;PATH_MAX];
if (getcwd(original_dir, sizeof(original_dir)) == NULL) {
perror("保存原始目录失败");
exit(EXIT_FAILURE);
}
printf("原始目录: %s\n", original_dir);

// 创建测试目录
const char *test_dir = "test_getcwd_dir";
if (mkdir(test_dir, 0755) == -1 && errno != EEXIST) {
perror("创建测试目录失败");
} else {
printf("创建测试目录: %s\n", test_dir);

// 切换到测试目录
if (chdir(test_dir) == -1) {
perror("切换目录失败");
} else {
printf("切换到测试目录\n");

// 获取当前目录
result = getcwd(buffer, sizeof(buffer));
if (result != NULL) {
printf("切换后当前目录: %s\n", buffer);

// 验证是否正确切换
if (strstr(buffer, test_dir) != NULL) {
printf("目录切换验证成功\n");
}
}

// 在测试目录中创建子目录
const char *sub_dir = "sub_directory";
if (mkdir(sub_dir, 0755) == -1 && errno != EEXIST) {
perror("创建子目录失败");
} else {
printf("创建子目录: %s\n", sub_dir);

// 切换到子目录
if (chdir(sub_dir) == -1) {
perror("切换到子目录失败");
} else {
printf("切换到子目录\n");

result = getcwd(buffer, sizeof(buffer));
if (result != NULL) {
printf("子目录路径: %s\n", buffer);
}
}
}
}

// 返回原始目录
if (chdir(original_dir) == -1) {
perror("返回原始目录失败");
} else {
printf("返回原始目录\n");
result = getcwd(buffer, sizeof(buffer));
if (result != NULL) {
printf("确认当前目录: %s\n", buffer);
}
}
}

// 示例4: 错误处理演示
printf("\n示例4: 错误处理演示\n");

// 测试缓冲区太小的情况
char tiny_buffer&#91;5];
result = getcwd(tiny_buffer, sizeof(tiny_buffer));
if (result == NULL) {
if (errno == ERANGE) {
printf("缓冲区太小错误处理正确: %s\n", strerror(errno));
} else {
printf("其他错误: %s\n", strerror(errno));
}
}

// 测试无效参数
result = getcwd(buffer, 0);
if (result == NULL) {
if (errno == EINVAL) {
printf("无效参数处理正确: %s\n", strerror(errno));
}
}

// 示例5: 实际应用场景
printf("\n示例5: 实际应用场景\n");

// 场景1: 程序配置文件定位
printf("场景1: 程序配置文件定位\n");
result = getcwd(buffer, sizeof(buffer));
if (result != NULL) {
char config_path&#91;PATH_MAX * 2];
snprintf(config_path, sizeof(config_path), "%s/.myapp/config", buffer);
printf("配置文件路径: %s\n", config_path);

// 检查配置文件是否存在
if (access(config_path, F_OK) == 0) {
printf("配置文件存在\n");
} else {
printf("配置文件不存在,将创建默认配置\n");
}
}

// 场景2: 相对路径转换为绝对路径
printf("场景2: 相对路径处理\n");
const char *relative_paths&#91;] = {"./file.txt", "../parent_dir", "subdir/file"};

for (int i = 0; i < 3; i++) {
result = getcwd(buffer, sizeof(buffer));
if (result != NULL) {
char absolute_path&#91;PATH_MAX * 2];
snprintf(absolute_path, sizeof(absolute_path), "%s/%s", buffer, relative_paths&#91;i]);
printf(" %s -> %s\n", relative_paths&#91;i], absolute_path);
}
}

// 场景3: 目录操作安全检查
printf("场景3: 目录操作安全检查\n");
char current_dir&#91;PATH_MAX];
char previous_dir&#91;PATH_MAX];

// 保存当前目录
if (getcwd(current_dir, sizeof(current_dir)) != NULL) {
printf("当前工作目录: %s\n", current_dir);

// 执行一些目录操作
// ... 目录操作代码 ...

// 检查目录是否发生变化
if (getcwd(previous_dir, sizeof(previous_dir)) != NULL) {
if (strcmp(current_dir, previous_dir) != 0) {
printf("警告: 工作目录已改变\n");
printf("原目录: %s\n", current_dir);
printf("现目录: %s\n", previous_dir);
} else {
printf("工作目录保持不变\n");
}
}
}

// 场景4: 日志记录中的目录信息
printf("场景4: 日志记录\n");
time_t current_time = time(NULL);
result = getcwd(buffer, sizeof(buffer));
if (result != NULL) {
printf("&#91;%s] INFO: 程序在目录 '%s' 中启动\n",
ctime(&current_time), buffer);
}

// 示例6: 跨平台兼容性考虑
printf("\n示例6: 跨平台兼容性\n");

// 获取系统路径限制
long path_max = pathconf(".", _PC_PATH_MAX);
if (path_max == -1) {
path_max = PATH_MAX;
printf("使用默认PATH_MAX: %ld\n", path_max);
} else {
printf("系统PATH_MAX: %ld\n", path_max);
}

// 使用动态分配确保足够空间
char *safe_buffer = getcwd(NULL, 0);
if (safe_buffer != NULL) {
printf("动态分配确保安全: %s\n", safe_buffer);
printf("路径长度: %zu 字节\n", strlen(safe_buffer));
free(safe_buffer);
}

// 示例7: 性能对比测试
printf("\n示例7: 性能对比测试\n");

// 测试预分配缓冲区的性能
clock_t start = clock();
for (int i = 0; i < 10000; i++) {
getcwd(buffer, sizeof(buffer));
}
clock_t preallocated_time = clock() - start;

// 测试动态分配的性能
start = clock();
for (int i = 0; i < 10000; i++) {
char *temp = getcwd(NULL, 0);
if (temp != NULL) {
free(temp);
}
}
clock_t dynamic_time = clock() - start;

printf("预分配缓冲区 10000 次调用耗时: %f 秒\n",
((double)preallocated_time) / CLOCKS_PER_SEC);
printf("动态分配 10000 次调用耗时: %f 秒\n",
((double)dynamic_time) / CLOCKS_PER_SEC);
printf("预分配方式通常更快\n");

// 清理测试目录
printf("\n清理测试资源...\n");
if (access(test_dir, F_OK) == 0) {
if (rmdir(test_dir) == -1) {
printf("删除测试目录失败: %s\n", strerror(errno));
} else {
printf("删除测试目录完成\n");
}
}

return 0;
}
data-ad-format="auto" data-full-width-responsive="true">