Linux C语言编程教程该怎么学?

99ANYc3cd6
预计阅读时长 34 分钟
位置: 首页 C语言 正文

Linux C 语言编程综合教程

本教程将分为以下几个主要部分:

linux c语言编程教程
(图片来源网络,侵删)
  1. 准备篇:环境搭建与基础工具 - 如何在你的 Linux 系统上准备好编程环境。
  2. 入门篇:第一个 C 程序 - 编写、编译并运行你的第一个 "Hello, World!" 程序。
  3. 核心篇:C 语言基础 - 复习 C 语言的核心语法,并结合 Linux 环境进行讲解。
  4. 进阶篇:Linux 系统编程 - 深入讲解如何在 C 程序中与 Linux 内核交互,包括文件 I/O、进程、信号等。
  5. 实战篇:构建一个简单的 Shell - 通过一个完整的项目,将所学知识融会贯通。
  6. 工具篇:提升开发效率 - 介绍 GCC 调试、Makefile、GDB 等必备工具。
  7. 资源与总结 - 推荐书籍和进一步学习的方向。

第一部分:准备篇 - 环境搭建与基础工具

在开始之前,你需要确保你的 Linux 系统已经安装了必要的开发工具。

选择你的 Linux 发行版

  • Ubuntu/Debian: 对新手友好,社区庞大。
  • Fedora/CentOS/RHEL: 稳定,常用于服务器和企业环境。
  • Arch Linux: 提供最新的软件,但需要更多手动配置。

安装 GCC 和 Make

GCC (GNU Compiler Collection) 是编译 C 程序的核心工具。make 是一个自动化构建工具,用于管理大型项目的编译过程。

在基于 Debian/Ubuntu 的系统上:

sudo apt update
sudo apt install build-essential

build-essential 包包会自动安装 gcc, g++, make 等核心编译工具。

linux c语言编程教程
(图片来源网络,侵删)

在基于 Fedora/CentOS 的系统上:

sudo dnf groupinstall "Development Tools"

Development Tools 软件组包含了所有必要的编译和构建工具。

选择一个代码编辑器

  • Vim/Neovim: 强大的终端编辑器,学习曲线陡峭但效率极高。
  • Emacs: 另一个经典的“神级”编辑器,高度可定制。
  • VS Code (Visual Studio Code): 现代、功能丰富的图形化编辑器,通过插件可以提供出色的 C 语言开发体验。
  • Gedit: 简单易用的图形化编辑器,适合初学者。

推荐: 初学者可以从 VS Code 开始,它提供了直观的界面和丰富的提示,当你熟悉后,可以挑战 Vim


第二部分:入门篇 - 你的第一个 C 程序

让我们创建一个经典的 "Hello, World!" 程序。

linux c语言编程教程
(图片来源网络,侵删)

创建源代码文件

打开你的编辑器,创建一个名为 hello.c 的文件,并输入以下代码:

// hello.c
#include <stdio.h> // 引入标准输入输出库
int main() {
    printf("Hello, Linux World!\n");
    return 0; // 程序正常退出
}
  • #include <stdio.h>: 这行代码告诉编译器,我们需要使用 stdio.h (Standard Input/Output) 库中的函数,printf
  • int main(): 这是 C 程序的入口函数,程序从这里开始执行。
  • printf(...): 用于在屏幕上打印文本。
  • \n: 是一个换行符。
  • return 0;: 表示程序成功执行完毕并返回 0 给操作系统。

编译源代码

打开终端,进入 hello.c 文件所在的目录,使用 gcc 命令进行编译:

gcc hello.c -o hello
  • gcc: 调用 GCC 编译器。
  • hello.c: 你的源文件。
  • -o hello: 指定输出的可执行文件名为 hello,如果不加 -o,默认会生成一个名为 a.out 的文件。

运行程序

编译成功后,你会得到一个名为 hello 的可执行文件,在终端中输入以下命令来运行它:

./hello
  • 表示在当前目录下寻找并执行该程序,在 Linux 中,直接输入 hello 可能会找不到,因为它不在系统的 PATH 环境变量中。

你应该会在终端看到输出:

Hello, Linux World!

第三部分:核心篇 - C 语言基础

这部分假设你已经有 C 语言基础,我们将重点介绍在 Linux 环境下的一些特有实践。

头文件与库

在 Linux 中,C 语言的标准库头文件位于 /usr/include 目录下,系统级的头文件(如 unistd.h, sys/stat.h)也在这里,当你使用 #include <...> 时,编译器会自动在这里查找。

基本数据类型

与标准 C 一致,但要注意:

  • int: 在现代的 64 位 Linux 系统上,通常是 4 字节(32位)。
  • long long: 用于表示更大的整数。
  • char: 通常是 1 字节。

控制流

if, for, while, switch 等与标准 C 完全相同。

函数

Linux 系统编程充满了各种由内核提供的函数,

  • printf 来自 libc (C标准库)。
  • open, read, write 来自 unistd.h (系统调用)。

第四部分:进阶篇 - Linux 系统编程

这是 Linux C 编程的精髓,即通过 C 语言调用 Linux 内核提供的 API(系统调用)来与操作系统交互。

文件 I/O (文件操作)

C 标准库 (stdio.h) 提供了 fopen, fread, fwrite, fclose 等高级接口,而 Linux 系统调用提供了更底层的接口。

主要系统调用:

  • open(): 打开或创建一个文件。
  • read(): 从文件描述符中读取数据。
  • write(): 向文件描述符写入数据。
  • close(): 关闭一个文件描述符。

示例:使用 readwrite 复制文件

#include <stdio.h>
#include <unistd.h> // 用于 read, write, close
#include <fcntl.h>  // 用于 open
#include <stdlib.h> // 用于 exit
#define BUFFER_SIZE 1024
int main(int argc, char *argv[]) {
    if (argc != 3) {
        fprintf(stderr, "Usage: %s <source> <destination>\n", argv[0]);
        exit(EXIT_FAILURE);
    }
    int src_fd = open(argv[1], O_RDONLY); // 只读方式打开源文件
    if (src_fd == -1) {
        perror("Error opening source file");
        exit(EXIT_FAILURE);
    }
    int dest_fd = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, 0644); // 写入方式创建/截断目标文件,权限644
    if (dest_fd == -1) {
        perror("Error opening destination file");
        close(src_fd);
        exit(EXIT_FAILURE);
    }
    char buffer[BUFFER_SIZE];
    ssize_t bytes_read;
    while ((bytes_read = read(src_fd, buffer, BUFFER_SIZE)) > 0) {
        if (write(dest_fd, buffer, bytes_read) != bytes_read) {
            perror("Error writing to destination file");
            close(src_fd);
            close(dest_fd);
            exit(EXIT_FAILURE);
        }
    }
    if (bytes_read == -1) {
        perror("Error reading from source file");
    }
    close(src_fd);
    close(dest_fd);
    printf("File copied successfully.\n");
    return 0;
}

编译并运行:

gcc copy_file.c -o copy_file
./copy_file my_file.txt my_file_copy.txt

perror() 函数: 这是一个非常有用的函数,它会打印你传入的字符串,然后附加一个冒号和 errno 对应的错误信息,帮助你快速定位问题。

进程控制

  • fork(): 创建一个与当前进程几乎完全相同的子进程。fork() 调用一次,返回两次,在父进程中返回子进程的 PID,在子进程中返回 0。
  • exec(): 用一个新的程序替换当前进程的映像,通常与 fork() 结合使用,实现“创建子进程并执行新程序”。
  • wait(): 父进程调用此函数来等待子进程结束。
  • exit(): 终止当前进程。

示例:创建子进程并执行 ls 命令

#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#include <stdlib.h>
int main() {
    pid_t pid = fork(); // 创建子进程
    if (pid == -1) {
        perror("fork failed");
        exit(EXIT_FAILURE);
    }
    if (pid > 0) {
        // 父进程
        printf("Parent: Child with PID %d created.\n", pid);
        wait(NULL); // 等待子进程结束
        printf("Parent: Child has finished.\n");
    } else {
        // 子进程
        printf("Child: Executing 'ls -l'...\n");
        char *args[] = {"ls", "-l", NULL};
        execvp("ls", args); // 执行 ls -l 命令
        // execvp 成功,下面的代码不会被执行
        perror("execvp failed");
        exit(EXIT_FAILURE);
    }
    return 0;
}

信号

信号是 Linux 进程间通信的一种异步机制,当你按下 Ctrl+C 时,操作系统会向前台进程发送一个 SIGINT 信号。

  • signal(): 用于捕获和处理信号。

示例:捕获 SIGINT (Ctrl+C)

#include <stdio.h>
#include <signal.h>
#include <unistd.h>
void handle_sigint(int sig) {
    printf("\nCaught SIGINT! No longer exiting on Ctrl+C.\n");
    // 在这里可以执行清理工作
}
int main() {
    signal(SIGINT, handle_sigint); // 注册信号处理函数
    while (1) {
        printf("Program is running... Press Ctrl+C to test.\n");
        sleep(1);
    }
    return 0;
}

第五部分:实战篇 - 构建一个简单的 Shell

这是检验你学习成果的绝佳方式,我们将创建一个名为 myshell 的程序,它可以:

  1. 打印一个提示符(如 myshell>)。
  2. 读取用户输入的命令。
  3. 解析命令(ls -l)。
  4. 创建子进程并执行该命令。
  5. 等待命令执行完毕,然后再次显示提示符。
// myshell.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
#define MAX_LINE 80 // 最大命令长度
void parse_input(char *input, char **args) {
    char *token;
    int i = 0;
    token = strtok(input, " \n"); // 按空格和换行符分割
    while (token != NULL && i < MAX_LINE - 1) {
        args[i++] = token;
        token = strtok(NULL, " \n");
    }
    args[i] = NULL; // 参数列表必须以 NULL 
}
int main() {
    char input[MAX_LINE];
    char *args[MAX_LINE / 2 + 1]; // 命令参数列表
    while (1) {
        printf("myshell> ");
        fflush(stdout); // 确保提示符立即显示
        // 读取用户输入
        if (fgets(input, sizeof(input), stdin) == NULL) {
            break; // 处理 EOF (Ctrl+D)
        }
        // 解析输入
        parse_input(input, args);
        if (args[0] == NULL) {
            continue; // 空输入
        }
        // 内置命令 exit
        if (strcmp(args[0], "exit") == 0) {
            break;
        }
        pid_t pid = fork();
        if (pid == 0) {
            // 子进程
            execvp(args[0], args);
            perror("execvp failed"); // execvp 返回,说明执行失败
            exit(EXIT_FAILURE);
        } else if (pid > 0) {
            // 父进程
            wait(NULL); // 等待子进程结束
        } else {
            perror("fork failed");
        }
    }
    return 0;
}

编译并运行:

gcc myshell.c -o myshell
./myshell

现在你就有了一个可以运行 ls, pwd, echo hello 等简单命令的迷你 Shell 了!


第六部分:工具篇 - 提升开发效率

GDB (GNU Debugger) - 调试你的程序

当程序出现 bug 时,gdb 是你的好朋友。

使用步骤:

  1. 编译时加上 -g 选项:生成包含调试信息的可执行文件。
    gcc -g mybuggy.c -o mybuggy
  2. 启动 GDB
    gdb ./mybuggy
  3. 常用 GDB 命令
    • (gdb) break main(gdb) b main: 在 main 函数处设置断点。
    • (gdb) run(gdb) r: 运行程序。
    • (gdb) next(gdb) n: 下一行(不进入函数)。
    • (gdb) step(gdb) s: 下一行(进入函数)。
    • (gdb) print my_var(gdb) p my_var: 打印变量 my_var 的值。
    • (gdb) continue(gdb) c: 继续运行,直到下一个断点。
    • (gdb) quit: 退出 GDB。

Makefile - 自动化构建

当项目文件变多时,每次手动输入 gcc 命令变得非常繁琐。Makefile 定义了一系列规则,告诉 make 如何编译和链接你的程序。

一个简单的 Makefile 示例 (Makefile 文件内容):

# 定义变量
CC = gcc
CFLAGS = -Wall -g
TARGET = my_program
SRCS = main.c utils.c helper.c
OBJS = $(SRCS:.c=.o)
# 默认目标,当 make 不带参数时执行
all: $(TARGET)
# 链接规则:如何生成最终可执行文件
$(TARGET): $(OBJS)
    $(CC) $(CFLAGS) -o $@ $^
# 编译规则:如何从 .c 文件生成 .o 文件
%.o: %.c
    $(CC) $(CFLAGS) -c $< -o $@
# 清理生成的文件
clean:
    rm -f $(OBJS) $(TARGET)
# .PHONY 表示这是一个伪目标,不生成文件
.PHONY: all clean

使用方法:

  • make: 执行 all 目标,编译所有 .c 文件并链接成 my_program
  • make clean: 删除所有 .o 文件和最终的可执行文件 my_program

第七部分:资源与总结

推荐书籍

  1. 《C 程序设计语言》 (The C Programming Language, K&R): C 语言圣经,必读。
  2. 《C Primer Plus》: 内容详尽,适合初学者系统学习。
  3. 《Unix 环境高级编程》 (Advanced Programming in the Unix Environment, APUE): Linux 系统编程的“圣经”,深入浅出地讲解了几乎所有重要的 Unix API。
  4. 《Linux/UNIX 系统编程手册》 (Linux/UNIX System Programming): 另一本系统编程领域的巨著,内容非常全面。

在线资源

  • man 手册页: Linux 自带的最佳文档,在终端中输入 man 2 open 查看 open 系统调用的手册(2 代表系统调用)。
  • The Linux Programming Interface (TLPI) Online Resources: https://man7.org/tlpi/ 提供了书籍的示例代码和勘误。
  • Stack Overflow: 解决编程问题的绝佳社区。

学习 Linux C 编程是一个循序渐进的过程:

  1. 打好基础: 熟练掌握 C 语言语法。
  2. 熟悉工具: 学会使用 GCC, GDB, Make。
  3. 深入系统: 理解文件、进程、内存等核心概念,并学习如何通过系统调用与它们交互。
  4. 动手实践: 通过编写小程序(如 Shell, Web 服务器, 文件工具)来巩固知识。

祝你学习愉快!

-- 展开阅读全文 --
头像
dede根目录调用标签
« 上一篇 今天
织梦TAG如何添加缩略图?
下一篇 » 今天
取消
微信二维码
支付宝二维码

目录[+]