Linux程序设计从入门到实战(价值198元)全套教程资源分享

封面图

📖 资源简介

最近有朋友问Linux程序设计从入门到实战(价值198元)的学习资料,正好手头有一套比较完整的,就整理出来分享给大家。

✨ 资源亮点

  • 内容扎实:100节视频课程,跟着老师一步步操作,比自学摸索快得多。
  • 零基础友好:从环境搭建开始讲起,不需要有任何前置知识,纯新手也能入门。

📚 课程内容

资源清单

类型 数量
视频教程 100 节
压缩文件 0 个
合计 100

为什么要学”Linux 程序设计”

很多人把”会用 Linux”和”会 Linux 程序设计”混为一谈。前者是在命令行敲 ls、cd、grep,后者是用 C 语言直接调用内核提供的系统调用,写出在 Linux 上跑后台服务、网络代理、数据库引擎这类底层软件的能力。

当前端、客户端、业务后端都在向上层框架收敛时,真正有壁垒的工程师反而在往下走:云原生、存储、网络、数据库、性能优化、中间件,这些岗位几乎都要求你能读懂 epoll、mmap、io_uring 的源码级用法。这套课的价值,就是帮你把”应用层业务开发者”升级成”懂操作系统的底层工程师”。

适合谁学:

  • 想做 C/C++ 后台、嵌入式、驱动、云原生组件的同学;
  • 写 Java / Go / Python 但被”线上性能问题””内核参数调优”卡住的应用层工程师;
  • 准备面试后台开发岗、希望把”进程 / 线程 / IO / 网络”答到原理层的人。

一、Shell 与工具:程序员的”日常肌肉”

正式写 C 之前,先把命令行工具用熟。Linux 一切皆文件,绝大多数问题都能靠管道串起来解决。

权限与文件

Linux 用一个 9 位的权限位表示三组(user / group / other)的读、写、执行:

# -rwxr-xr--  =>  user=rwx, group=r-x, other=r--

![封面图](https://www.suyouke.com/wp-content/uploads/2026/09/doubao_img_022_20260922_113350-14.png)
chmod 755 script.sh      # rwxr-xr-x
chmod u+x script.sh      # 只给所有者加执行位
chown alice:dev app.log  # 改属主和属组

数字权限速查:r=4, w=2, x=1,三位相加即一组。

文本处理三剑客

# grep:过滤

![封面图](https://www.suyouke.com/wp-content/uploads/2026/09/doubao_img_022_20260922_113350-14.png)
grep -rn "TODO" ./src/ --include="*.c"

# awk:按列处理

![封面图](https://www.suyouke.com/wp-content/uploads/2026/09/doubao_img_022_20260922_113350-14.png)
ps aux | awk '$3 > 5.0 {print $2, $3"%", $11}'

# sed:流编辑

![封面图](https://www.suyouke.com/wp-content/uploads/2026/09/doubao_img_022_20260922_113350-14.png)
sed -i 's/old/new/g' config.ini

# find:按条件找文件

![封面图](https://www.suyouke.com/wp-content/uploads/2026/09/doubao_img_022_20260922_113350-14.png)
find . -name "*.log" -mtime +7 -delete

Shell 脚本基础

#!/usr/bin/env bash
set -euo pipefail   # 出错即退、未定义变量报错、管道失败即退

# 特殊变量:$0=脚本名 $#=参数个数 $@=所有参数 $?=上一条命令退出码

![封面图](https://www.suyouke.com/wp-content/uploads/2026/09/doubao_img_022_20260922_113350-14.png)
if [ $# -lt 1 ]; then
  echo "usage: $0 <name>" >&2
  exit 1
fi

for f in "$@"; do
  case "$f" in
    *.log)  echo "log file: $f" ;;
    *.conf) echo "config file: $f" ;;
    *)      echo "other: $f" ;;
  esac
done

# 函数:用 local 防止污染全局

![封面图](https://www.suyouke.com/wp-content/uploads/2026/09/doubao_img_022_20260922_113350-14.png)
greet() {
  local name="$1"
  echo "hello, $name"
  return 0
}
greet "world"

写脚本最常见的坑:不写 set -euo pipefail,导致错误被静默吞掉;或者不加引号,文件名带空格就崩。

二、C 语言系统编程:文件 I/O

系统调用 vs 标准库

Linux 提供两套 I/O 接口,必须分清:

接口 来源 缓冲 句柄类型
open/read/write/lseek 内核系统调用 无用户态缓冲 文件描述符 int fd
fopen/fread/fwrite/fprintf libc 标准库 有用户态缓冲 文件指针 FILE *
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>

int main(void) {
    int fd = open("hello.txt", O_WRONLY | O_CREAT | O_TRUNC, 0644);
    if (fd < 0) { perror("open"); return 1; }

    const char *msg = "hello, linux\n";
    ssize_t n = write(fd, msg, 14);
    if (n < 0) { perror("write"); }

    close(fd);
    return 0;
}

文件描述符是一个从 0 开始的小整数。每个进程默认打开 0(stdin)、1(stdout)、2(stderr),之后每次 open 都分配当前最小未用的 fd。理解 fd 表是理解重定向、管道、socket 的前提。

stat 与目录遍历

#include <sys/stat.h>
struct stat st;
if (stat("hello.txt", &st) == 0) {
    printf("size=%ld bytes, mode=%o\n", st.st_size, st.st_mode & 0777);
}

#include <dirent.h>
DIR *d = opendir(".");
struct dirent *ent;
while ((ent = readdir(d)) != NULL) {
    printf("%s\n", ent->d_name);
}
closedir(d);

三、进程:fork / exec / wait

Unix 进程模型一句话:进程靠 fork 克隆自己,靠 exec 换上新程序,靠 wait 回收子进程。

#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>

int main(void) {
    pid_t pid = fork();
    if (pid < 0) { perror("fork"); return 1; }

    if (pid == 0) {
        /* 子进程 */
        execlp("ls", "ls", "-l", NULL);
        perror("exec never returns on success");
        return 127;
    } else {
        /* 父进程 */
        int status;
        waitpid(pid, &status, 0);
        printf("child exit=%d\n", WEXITSTATUS(status));
    }
    return 0;
}

两个必须理解的概念:

  • 僵尸进程(Zombie):子进程退出了,但父进程没 wait,内核还保留它的退出状态。ps 里看到 Z 状态。解决办法:父进程及时 wait/waitpid,或忽略 SIGCHLD。
  • 孤儿进程:父进程先死了,子进程被 init(PID 1)收养。一般无害。

守护进程(daemon) 的标准套路:fork 一次让父进程退出 → setsid() 脱离会话 → 再 fork 一次防止重新拿终端 → 改工作目录到 / → 重定向 0/1/2 到 /dev/null。

四、信号:进程之间的”软中断”

#include <signal.h>
#include <unistd.h>
#include <stdio.h>

volatile sig_atomic_t stop = 0;

void on_sigint(int sig) {
    (void)sig;
    stop = 1;   /* 异步信号里只改 volatile sig_atomic_t 是安全的 */
}

int main(void) {
    struct sigaction sa = {0};
    sa.sa_handler = on_sigint;
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = 0;
    sigaction(SIGINT, &sa, NULL);

    while (!stop) {
        pause();
    }
    printf("bye\n");
    return 0;
}

要点:

  • 用 sigaction 而不是老的 signal(),后者在不同 Unix 上行为不一致。
  • 在信号处理函数里不要调用 printf / malloc 这类非异步信号安全函数。
  • SIGPIPE 默认会让进程在写一个已关闭的管道时直接死掉,网络服务里通常要 signal(SIGPIPE, SIG_IGN)。
  • 子进程退出时给父进程发 SIGCHLD,父进程在它里面 waitpid 回收。

五、线程与同步

Linux 线程是用 POSIX Threads(pthread)实现的,本质是”轻量级进程”,和进程共享地址空间。

#include <pthread.h>
#include <stdio.h>

static long counter = 0;
static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;

void *worker(void *arg) {
    (void)arg;
    for (int i = 0; i < 100000; i++) {
        pthread_mutex_lock(&lock);
        counter++;
        pthread_mutex_unlock(&lock);
    }
    return NULL;
}

int main(void) {
    pthread_t t[4];
    for (int i = 0; i < 4; i++) pthread_create(&t[i], NULL, worker, NULL);
    for (int i = 0; i < 4; i++) pthread_join(t[i], NULL);
    printf("counter=%ld\n", counter);   /* 不加锁会远小于 400000 */
    return 0;
}

同步原语对照表:

原语 用途 典型场景
pthread_mutex_t 互斥,保护临界区 共享计数器、链表
pthread_cond_t 等待某条件成立 生产者-消费者
pthread_rwlock_t 读写锁 读多写少的配置
pthread_barrier_t 线程齐步走 并行计算同步点

死锁四条件:互斥、持有并等待、不可抢占、循环等待。破坏任意一个即可——最实用的做法是所有线程以相同顺序加锁。

六、网络编程:从 socket 到 epoll

TCP 服务端骨架

#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <stdio.h>

int main(void) {
    int listen_fd = socket(AF_INET, SOCK_STREAM, 0);
    int opt = 1;
    setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));

    struct sockaddr_in addr = {0};
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = htonl(INADDR_ANY);
    addr.sin_port = htons(8080);

    bind(listen_fd, (struct sockaddr *)&addr, sizeof(addr));
    listen(listen_fd, 128);

    for (;;) {
        int cfd = accept(listen_fd, NULL, NULL);
        char buf[1024];
        ssize_t n = read(cfd, buf, sizeof(buf) - 1);
        if (n > 0) {
            buf[n] = '\0';
            write(cfd, "HTTP/1.1 200 OK\r\nContent-Length: 3\r\n\r\nok\n", 33);
        }
        close(cfd);
    }
    return 0;
}

经典三次握手 / 四次挥手必须背熟:

  • 三次握手:SYN → SYN+ACK → ACK,目的是双方都确认彼此的收发能力。
  • 四次挥手:FIN → ACK → FIN → ACK,因为 TCP 全双工,关闭是两个方向分别进行。

为什么需要 IO 多路复用

上面的服务端每来一个连接就 accept + read + close,同时只能处理一个客户端。要支持并发,常见思路:

模型 思路 问题
阻塞 IO + 每连接一线程 accept 后 pthread_create 连接数一上去,线程爆炸
select / poll 一个线程轮询所有 fd fd 多了每次遍历 O(n)
epoll 内核事件通知,只返回就绪的 fd 高并发首选
异步 IO(io_uring) 内核完成后回调 新一代,生态还在完善

epoll 的三个系统调用:

int epfd = epoll_create1(0);

struct epoll_event ev = {0};
ev.events  = EPOLLIN;
ev.data.fd = listen_fd;
epoll_ctl(epfd, EPOLL_CTL_ADD, listen_fd, &ev);

struct epoll_event events[128];
int n = epoll_wait(epfd, events, 128, -1);
for (int i = 0; i < n; i++) {
    /* events[i].data.fd 就是就绪的 fd */
}

Reactor 模式就是基于 epoll:一个主线程跑 epoll_wait,就绪事件分发到对应的 handler 处理。Redis、Nginx、Netty 全是这个套路。

七、编译、链接与调试

GCC 四步走

# 预处理(宏展开、头文件插入)

![封面图](https://www.suyouke.com/wp-content/uploads/2026/09/doubao_img_022_20260922_113350-14.png)
gcc -E hello.c -o hello.i
# 编译(C -> 汇编)

![封面图](https://www.suyouke.com/wp-content/uploads/2026/09/doubao_img_022_20260922_113350-14.png)
gcc -S hello.i -o hello.s
# 汇编(汇编 -> 机器码 .o)

![封面图](https://www.suyouke.com/wp-content/uploads/2026/09/doubao_img_022_20260922_113350-14.png)
gcc -c hello.s -o hello.o
# 链接(多个 .o 拼成可执行文件)

![封面图](https://www.suyouke.com/wp-content/uploads/2026/09/doubao_img_022_20260922_113350-14.png)
gcc hello.o -o hello

理解这四步,才能看懂”为什么改了头文件要全量重编””为什么加个 -fPIC 才能编动态库”。

静态库 vs 动态库

# 静态库:把 .ar 包进可执行文件

![封面图](https://www.suyouke.com/wp-content/uploads/2026/09/doubao_img_022_20260922_113350-14.png)
ar rcs libhello.a hello.o
gcc main.c -L. -lhello -o app_static

# 动态库:运行时才加载

![封面图](https://www.suyouke.com/wp-content/uploads/2026/09/doubao_img_022_20260922_113350-14.png)
gcc -fPIC -shared hello.c -o libhello.so
# 让程序找到 .so

![封面图](https://www.suyouke.com/wp-content/uploads/2026/09/doubao_img_022_20260922_113350-14.png)
export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH
gcc main.c -L. -lhello -o app_dyn

动态库找不到的经典报错 error while loading shared libraries,解决方法就是把 .so 路径加进 LD_LIBRARY_PATH,或写到 /etc/ld.so.conf.d/ 后 ldconfig。

GDB 调试

gcc -g -O0 demo.c -o demo       # 必须带 -g
gdb ./demo
(gdb) break main
(gdb) run
(gdb) next / step / finish
(gdb) print var
(gdb) backtrace
(gdb) watch counter

线上 core dump 分析:gdb ./app core.xxx,然后 bt full。

学习路线导读

这套课 100 节,按从易到难大致可拆成五段:

  1. Linux 环境与基本命令:装系统、ssh、文件权限、进程管理、管道重定向。
  2. Shell 脚本:变量、控制流、函数、文本处理。
  3. C 语言系统编程:文件 I/O、进程、信号。
  4. 线程与同步:pthread、互斥锁、条件变量。
  5. 网络编程与工程化:socket、epoll、Makefile、静态/动态库、GDB。

建议每章都边看边敲,不要只看视频。系统编程课和 Web 课最大的区别是——你抄一遍代码它就能跑,跑不通就是你没理解。

高频面试题

  • fork 之后父子进程共享哪些资源、不共享哪些?(共享文件描述符表、内存映射;不共享地址空间、文件偏移……注意 fork 后文件偏移是共享的)
  • 僵尸进程怎么产生?怎么避免?
  • select / poll / epoll 区别?epoll 为什么高效?(O(n) 遍历 vs O(1) 就绪通知;红黑树 + 就绪链表)
  • 什么是惊群?怎么避免?
  • 进程间通信(IPC)有哪几种?各自适用场景?(管道 / FIFO / 消息队列 / 共享内存 / 信号量 / Unix Domain Socket)
  • TCP 为什么三次握手、四次挥手?TIME_WAIT 为什么要等 2MSL?
  • 动态库和静态库的区别?什么是动态链接的符号可见性?

常见踩坑 FAQ

Q:写的 socket 程序 bind 时报 Address already in use? A:加 SO_REUSEADDR。这是 TIME_WAIT 残留导致的,开发期几乎必踩。

Q:fork 后 printf 输出多了一行? A:stdio 默认行缓冲,重定向到文件时变成全缓冲,fork 会把缓冲区一起复制一份,父进程退出时再 flush 一次。fflush(stdout) 或加 \n 可解。

Q:多线程程序加了锁还是结果不对? A:检查是不是在没加锁的代码路径也改了同一个变量,或者锁的粒度太粗把临界区写大了。先用 valgrind --tool=helgrind 跑一遍。

Q:make 时找不到头文件? A:用 -I/path/to/include 告诉 gcc;找库用 -L/path/to/lib + -lname。这两个参数 90% 的编译错误都在它们上。

总结

Linux 程序设计是一门”慢功夫”,但天花板极高。它不像 Web 框架那样半个月就能出活,但一旦你把进程、文件描述符、epoll、mmap 这些底层概念吃透,上层用什么语言、什么框架都是降维打击。

学习建议:

  • 先在自己机器上装一台虚拟机(Ubuntu 或 Debian),所有实验都在里面做,不要在公司开发机上瞎搞。
  • 每学一个系统调用,都先写一个最小可运行 demo,再去看别人的项目怎么用。
  • 配合《Unix 环境高级编程》(APUE)当字典,视频 + 书 + 手动 debug 三件套。
  • 不要一上来啃内核源码,先把用户态 API 用熟,再回头看内核实现会顺很多。

资源获取

💡 建议:尽快保存到本地网盘或电脑,避免分享链接后期失效。


整理不易,如果对你有帮助,欢迎分享给更多需要的朋友。

Linux程序设计从入门到实战(价值198元)全套教程资源分享-速优课
Linux程序设计从入门到实战(价值198元)全套教程资源分享
此内容为付费阅读,请付费后查看
¥2
立即购买
您当前未登录!建议登陆后购买,可保存购买订单
付费阅读
© 版权声明
THE END
喜欢就支持一下吧
点赞13
评论 抢沙发

请登录后发表评论

    请登录后查看评论内容

温馨提示:
1、本内容转载于网络,版权归原作者所有!
2、本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
3、本内容若侵犯到你的版权利益,请联系我们,会尽快给予删除处理!