Linux C 编程核心函数详解

Linux C 编程核心函数详解

1. fork - 进程管理

函数介绍及归类

  • 类别: 系统调用 (System Call)
  • 头文件: #include
  • 作用: 创建一个当前进程的副本(子进程)。这是 Linux 下创建新进程的主要方式。

函数原型

1
2
#include 
pid_t fork(void);

功能

fork() 调用一次,返回两次。它会创建一个与调用进程(父进程)几乎完全相同的子进程。子进程会从 fork() 返回后的下一条指令开始执行。

参数

无参数。

返回值

  • 在父进程中: 返回新创建的子进程的进程 ID (PID),这是一个正整数。
  • 在子进程中: 返回 0。
  • 失败时: 在父进程中返回 -1,并设置全局变量 errno 来指示错误原因(如系统资源不足)。

相似函数或关联函数

  • vfork(): 类似于 fork(),但在子进程调用 exec_exit 之前,父进程会被阻塞。通常用于紧接着调用 exec 的场景,效率可能稍高。
  • wait(), waitpid(): 父进程用来等待子进程结束。
  • getpid(): 获取当前进程的 PID。
  • getppid(): 获取当前进程的父进程 PID。

示例代码 (C89)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include    /* printf, perror */
#include /* fork, getpid, getppid */
#include /* pid_t */
#include /* wait */

int main() {
pid_t pid;
int status;

/* 调用 fork 创建子进程 */
pid = fork();

if (pid `
* **作用:** 创建一个新进程,但与 `fork` 不同,它在子进程调用 `exec` 或 `_exit` 之前,共享父进程的地址空间,并且父进程会被阻塞。

#### 函数原型
```c
#include
pid_t vfork(void);

功能

vfork() 也调用一次,返回两次。它创建一个新进程,但这个新进程(子进程)在调用 exec 系列函数或 _exit 之前,与父进程共享内存(包括栈、数据段等)。在此期间,父进程是被挂起的。这使得 vfork 在紧接着调用 exec 时非常高效,因为它避免了复制父进程的页表。

参数

无参数。

返回值

  • 在父进程中: 返回新创建的子进程的 PID。
  • 在子进程中: 返回 0。
  • 失败时: 在父进程中返回 -1,并设置 errno

相似函数或关联函数

  • fork(): 更通用,子进程独立于父进程。
  • exec() 系列函数 (execl, execv, execle, execve, execlp, execvp): 用新程序替换当前进程的镜像。

示例代码 (C89)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include    /* printf, perror */
#include /* vfork, getpid, getppid, _exit */
#include /* pid_t */

int main() {
pid_t pid;
int shared_var = 10; /* 父子进程共享的变量 */

printf("Before vfork, shared_var = %d\n", shared_var);

/* 调用 vfork 创建子进程 */
pid = vfork();

if (pid `
* **作用:** 执行一个 shell 命令字符串。它内部通常通过调用 `fork`、`exec` 和 `wait` 来实现。

#### 函数原型
```c
#include
int system(const char *command);

功能

system() 函数将 command 字符串传递给系统的命令处理器(通常是 shell,如 /bin/sh)来执行。它是一个方便的函数,可以让你在 C 程序中执行外部命令。

参数

  • command: 指向以空字符结尾的字符串,该字符串包含了要执行的命令及其参数。

返回值

  • 成功: 返回命令执行后的退出状态。这个状态可以通过 WIFEXITED, WEXITSTATUS 等宏来解析(类似 wait)。
  • command 为 NULL: 如果系统有命令处理器可用,则返回非零值;否则返回 0。这可以用来检查 system 是否可用。
  • 失败或错误: 返回 -1,并设置 errno(例如,无法创建子进程)。
  • 命令本身执行失败: 返回由命令处理器报告的状态(通常是命令的退出码)。

相似函数或关联函数

  • fork(), exec() 系列, wait(): system 内部就是用这些函数实现的,提供了更底层和灵活的控制。
  • popen(), pclose(): 可以执行命令并获取其输出(通过管道)。

示例代码 (C89)

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
#include   /* printf, perror */
#include /* system */

int main() {
int result;

/* 检查 system 是否可用 */
if (system(NULL) == 0) {
printf("Command processor is not available.\n");
return 1;
}

printf("Command processor is available.\n");

/* 执行一个简单的命令 */
printf("\n--- Executing 'echo Hello from system call' ---\n");
result = system("echo Hello from system call");
if (result == -1) {
perror("system call failed");
return 1;
} else {
printf("Command 'echo ...' finished with status %d\n", result);
/* 注意:直接的 result 值可能包含更多信息,需要用 wait 宏解析 */
/* 为简化,这里只打印原始值 */
}

/* 执行一个列出文件的命令 */
printf("\n--- Executing 'ls -l' ---\n");
result = system("ls -l");
if (result == -1) {
perror("system call failed");
} else {
printf("Command 'ls -l' finished with status %d\n", result);
}

/* 执行一个会失败的命令 */
printf("\n--- Executing 'nonexistentcommand' ---\n");
result = system("nonexistentcommand");
if (result == -1) {
perror("system call failed (this might be due to fork/exec failure)");
} else {
printf("Command 'nonexistentcommand' finished with status %d\n", result);
/* 这里的 status 通常表示命令未找到 */
}

printf("\nMain program ending.\n");
return 0;
}

4. strlen - 字符串处理

函数介绍及归类

  • 类别: 标准库函数 (Standard Library Function)
  • 头文件: #include
  • 作用: 计算 C 风格字符串(以 \0 结尾)的长度。

函数原型

1
2
#include 
size_t strlen(const char *str);

功能

strlen() 函数遍历字符串 str,从第一个字符开始计数,直到遇到终止符 \0(不包括 \0),然后返回计数的字符数。

参数

  • str: 指向以 \0 结尾的字符串。

返回值

返回字符串 str 中字符的个数(不包括结尾的 \0 字符)。返回类型 size_t 是一个无符号整数类型。

相似函数或关联函数

  • sizeof: 这是一个运算符,不是函数。对于字符数组,sizeof 返回整个数组的大小(包括 \0),而 strlen 返回实际内容的长度。
  • strnlen(): (C99/C11) 类似 strlen,但会限制搜索长度,防止读取超出指定范围的内存。

示例代码 (C89)

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
#include   /* printf */
#include /* strlen */

int main() {
char str1[] = "Hello"; /* 编译器自动添加 \0 */
char str2[20] = "World"; /* 数组大小为 20,但内容只有 6 个字符(包括 \0) */
const char *str3 = "This is a longer string.";
char str4[] = {'N', 'o', ' ', 'N', 'u', 'l', 'l'}; /* 危险!没有 \0 */

size_t len1, len2, len3;

len1 = strlen(str1);
len2 = strlen(str2);
len3 = strlen(str3);

printf("String 1: \"%s\"\n", str1);
printf("Length of str1 (strlen): %u\n", (unsigned int)len1);
printf("Size of str1 array (sizeof): %u\n", (unsigned int)sizeof(str1)); /* 包括 \0 */

printf("\nString 2: \"%s\"\n", str2);
printf("Length of str2 (strlen): %u\n", (unsigned int)len2);
printf("Size of str2 array (sizeof): %u\n", (unsigned int)sizeof(str2)); /* 包括 \0 */

printf("\nString 3: \"%s\"\n", str3);
printf("Length of str3 (strlen): %u\n", (unsigned int)len3);

printf("\n--- Important Note ---\n");
printf("String 4 is not null-terminated. Calling strlen on it leads to undefined behavior.\n");
printf("It might crash or run forever. Uncommenting the next lines is dangerous.\n");
/* 危险!不要对没有 \0 的字符串调用 strlen */
/* printf("Length of str4 (UNDEFINED BEHAVIOR!): %u\n", (unsigned int)strlen(str4)); */

return 0;
}

5. strchr - 字符串处理

函数介绍及归类

  • 类别: 标准库函数 (Standard Library Function)
  • 头文件: #include
  • 作用: 在字符串中查找第一次出现的指定字符。

函数原型

1
2
#include 
char *strchr(const char *str, int c);

功能

strchr() 函数在字符串 str 中从左到右搜索字符 c(转换为 char 类型进行比较)。搜索包括终止符 \0

参数

  • str: 指向要搜索的以 \0 结尾的字符串。
  • c: 要搜索的字符,以 int 类型传递,但在比较时会转换为 unsigned char

返回值

  • 找到: 返回指向字符串 str 中第一次出现字符 c 的指针。
  • 未找到: 返回 NULL

相似函数或关联函数

  • strrchr(): 查找字符在字符串中最后一次出现的位置。
  • strstr(): 查找一个子字符串在另一个字符串中第一次出现的位置。
  • strpbrk(): 查找字符串中第一个匹配指定字符集中任意字符的位置。

示例代码 (C89)

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
#include   /* printf */
#include /* strchr */

int main() {
const char *str = "This is a sample string.";
char target_char = 's';
char *result_ptr;

printf("String to search: \"%s\"\n", str);
printf("Character to find: '%c'\n", target_char);

/* 查找第一次出现 's' 的位置 */
result_ptr = strchr(str, (int)target_char);

if (result_ptr != NULL) {
printf("First occurrence of '%c' found at position: %ld\n",
target_char, (long)(result_ptr - str)); /* 计算偏移量 */
printf("Substring from first '%c': \"%s\"\n", target_char, result_ptr);

/* 查找下一个 's' */
printf("\n--- Searching for next occurrence ---\n");
result_ptr = strchr(result_ptr + 1, (int)target_char); /* 从下一个位置开始搜索 */
if (result_ptr != NULL) {
printf("Second occurrence of '%c' found at position: %ld\n",
target_char, (long)(result_ptr - str));
printf("Substring from second '%c': \"%s\"\n", target_char, result_ptr);
} else {
printf("No more occurrences of '%c' found.\n", target_char);
}

} else {
printf("Character '%c' not found in the string.\n", target_char);
}

/* 查找字符串结尾符 '\0' */
printf("\n--- Searching for null terminator ---\n");
result_ptr = strchr(str, '\0');
if (result_ptr != NULL) {
printf("Null terminator '\\0' found at position: %ld\n", (long)(result_ptr - str));
printf("Pointer points to: '%c' (ASCII value %d)\n", *result_ptr, (int)*result_ptr);
}

/* 查找一个不存在的字符 */
printf("\n--- Searching for a character that doesn't exist ---\n");
result_ptr = strchr(str, 'z');
if (result_ptr != NULL) {
printf("Character 'z' found? This is unexpected.\n");
} else {
printf("Character 'z' not found, as expected. strchr returned NULL.\n");
}

return 0;
}

data-ad-format="auto" data-full-width-responsive="true">