当前位置: 首页 > news >正文

Linux C学习路线全概及知识点笔记2(仅供个人参考)


提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

目录

文章目录

1,进程创建、回收(以linux为例)

1.1 进程创建流程

1.2 进程回收机制

1.3 源文件变成可执行程序的过程

1.3.1 详解

1.3.2 gcc命令细化

1.3.3 可执行文件加载为进程的过程(Linux 视角)

1.4 总结框架表

2,crontab、at命令(待补充,用于定时备份等)

3,进程间通信

3.1 信号量

3.1.1 定义

3.1.2 信号量的类型

3.2 信号量在进程间通信中的作用

3.3 Linux下的信号量实现方式

3.4 System V 信号量详解(进程间通信重点)

3.4.1 使用步骤

3.4.2 核心结构和函数原型

3.4.3 典型代码示例(进程间同步)

3.5 信号量使用中的常见注意事项

4,POSIX 信号量

4.1 POSIX信号量头文件与链接方式

4.2 POSIX信号量类型

4.3 常用函数接口(详细对照表)

4.4 使用命名信号量(适用于进程间)

4.4.1 创建和初始化

4.4.2 使用信号量(同步)

4.4.3 关闭与释放资源

4.4.4 示例:两个进程同步输出

4.5 使用匿名信号量(适用于线程或内存共享)

4.5.1 初始化匿名信号量

4.5.2 使用方式

4.5.3 销毁信号量

4.5.4 示例:线程互斥访问共享资源

5,消息队列

5.1 消息队列定义

5.2 消息队列的主要特点

5.3 System V 消息队列关键结构与系统调用

5.3.1 创建或获取消息队列:msgget()

5.3.2 消息结构

5.3.3 发送消息:msgsnd()

5.3.4 接收消息:msgrcv()

5.3.5 控制消息队列:msgctl()

5.3.6 示例程序

5.3.7 调试建议

6,共享内存

6.1 定义

6.2 特点

6.3 System V共享内存相关系统调用

6.4 使用流程概览

6.5 共享内存函数讲解

 6.5.1 创建共享内存段:shmget()

6.5.2 映射共享内存段:shmat()

6.5.3 分离共享内存段:shmdt()

6.5.4 控制共享内存段:shmctl()

6.6 共享内存示例代码(两个进程)

6.6.1 写入进程(write.c)

6.6.2 读取进程(reader.c)

6.7 调试与实用技巧

7,信号的基本概念

7.1 信号的发送与接收

7.2 捕捉与忽略信号

7.2.1 忽略信号

7.3 阻塞信号

7.4 sigaction():更强大的信号处理

7.5 信号与进程控制

7.6 信号的实际应用场景

8,线程创建

8.1 线程与进程的区别

8.2 POSIX线程库(pthread)基础

8.2.1 创建线程的函数

8.2.2 示例:创建一个简单线程

8.3 等待线程结束(pthread_join)

8.4 线程生命周期简图

8.5 线程相关函数整理

8.6 常见问题与注意事项

9,线程同步与互斥的基本概念

9.1 互斥锁(pthread_mutex_t)概述

9.1.2 互斥锁的定义与初始化

9.1.3 使用互斥锁的基本流程

9.1.4 示例代码:两个线程并发写共享变量

9.2 互斥锁函数一览

9.3 互斥锁类型说明(高级)

9.4 常见问题与调试建议

9.5 互斥锁使用场景分析

10,什么是守护进程(Daemon Process)

10.1 守护进程的常见用途

10.2 如何编写一个守护进程(用户态实现)

10.2.1 示例:为守护进程添加信号处理(优雅的退出)

10.2.2 与 systemd 配合的守护进程管理(现代Linux系统)

11,库的基本概念

11.1 什么是库?

11.2 静态库 VS 动态库 对比分析

11.3 静态库和动态库的制作方法(含完整示例)

11.3.1 制作静态库

11.3.1.1 使用静态库

11.4 制作动态库 .so

11.4.1 编译步骤

11.4.2 使用动态库

11.5 关键技术知识点补充

11.6 建议与实践经验



1,进程创建、回收(以linux为例)

        在linux系统中,“进程”是程序的运行实例。我们以fork()和exec()为切入点:

1.1 进程创建流程

阶段内容说明
fork()创建一个新的子进程,子进程复制父进程的地址空间,但逻辑上是两个独立进程。
exec()子进程可以通过 exec 系列函数加载一个新的程序映像,替换自己的代码段、数据段等。
clone()更底层的创建方式(底层系统调用),fork() 等也基于 clone() 实现。

示例:

        

#include <unistd.h>
#include <sys/types.h>
#included <stdio.h>int main()
{pid_t pid = fork();if (pid == 0) {// 子进程printf("子进程,PID = %d\n", getpid());execlp("ls", "ls", "-l", NULL);} else if (pid > 0) {// 父进程printf("父进程,PID = %d\n", getpid());wait(NULL); // 等待子进程结束} else {printf("Fork failed!\n");}return 0;
}

1.2 进程回收机制

        子进程终止时,内核会将其状态保留(称为“僵尸进程”),直到父进程调用wait()或waitpid()将其资源释放。

情况处理方式
父进程调用 wait()内核回收子进程资源
父进程未调用 wait()子进程成为“僵尸进程”,资源占用不释放
父进程提前结束子进程被 init 进程收养,由它负责回收

1.3 源文件变成可执行程序的过程

        整个流程可以分为四个阶段:预处理、编译、汇编、连接。

1.3.1 详解

阶段工具输入输出说明
预处理cpp.c 文件.i 文件展开宏、处理头文件 #include、删除注释
编译cc1.i 文件.s 文件将 C 源代码翻译为汇编语言
汇编as.s 文件.o 文件汇编器把汇编代码翻译为机器码的目标文件
链接ld.o 文件和库文件可执行文件将多个 .o 文件和库链接成一个完整的可执行程序

1.3.2 gcc命令细化

命令说明
gcc -E hello.c -o hello.i仅预处理
gcc -S hello.i -o hello.s编译为汇编
gcc -c hello.s -o hello.o汇编为目标文件
gcc hello.o -o hello链接成可执行文件

1.3.3 可执行文件加载为进程的过程(Linux 视角)

        当你运行一个可执行程序,Linux内核将执行以下操作:

1)shell调用execve()系统调用

2)内核解析ELF文件结构

        验证头部信息

        读取程序头表(Program Header Table)

3)内核为进程分配内存

        映射代码段、数据段

        设置堆栈

4)加载器准备环境

        复制命令行参数和环境变量到新进程内存

        设置入口地址

5)CPU切换到入口地址

        开始执行用户代码(即main函数)

1.4 总结框架表

内容描述
进程创建方式fork、clone、exec 系列函数
进程回收wait/waitpid 回收子进程资源
编译四阶段预处理 → 编译 → 汇编 → 链接
可执行程序加载ELF 分析 → 映射内存 → 准备堆栈 → 切换执行
系统调用接口用户态通过 syscall 进入内核态

2,crontab、at命令(待补充,用于定时备份等)

3,进程间通信

3.1 信号量

3.1.1 定义

        信号量(Semaphore)是一种特殊的整型变量,用于在进程或线程之间实现同步和互斥控制。

3.1.2 信号量的类型

类型说明
计数信号量(Counting Semaphore)允许多个资源同时被访问,如连接池、线程池
二值信号量(Binary Semaphore)取值仅为0或1,等价于互斥锁,用于互斥控制

3.2 信号量在进程间通信中的作用

场景用途
控制共享资源的访问避免多个进程同时访问同一资源
同步操作保证某些操作顺序执行
实现临界区(Critical Section)控制某代码块只能被一个进程进入执行

3.3 Linux下的信号量实现方式

机制类型用于接口
System V 信号量进程间通信semgetsemopsemctl
POSIX 信号量进程/线程间sem_initsem_wait

3.4 System V 信号量详解(进程间通信重点)

3.4.1 使用步骤

步骤函数描述
1semget创建或获取一个信号量集合
2semctl控制信号量的属性,如初始化、删除等
3semopP/V 操作(即 wait/signal 操作)

3.4.2 核心结构和函数原型

senget(); 创建或获取信号量集合

int semget(key_t key, int nsems, int semflg);key        标识唯一信号量集,可通过fork生成
nsems      创建信号量个数
semflg     权限设置,如IPC_CREAT

semctl(); 控制信号量(初始化、删除等)

int semctl(int semid, int semnum, int cmd, ...);常用命令:SETVAL:设置信号量的值IPC_RMID:删除信号量GETVAL:获取当前值

semop(); 信号量操作(P/V操作)

int semop(int semid, struct sembuf *sops, size_t nsops);struct sembuf {unsigned short sem_num; // 信号量索引short sem_op; //操作数(-1 p操作,+1 v操作)short sem_flg; // 0或IPC_NOWAIT
};

3.4.3 典型代码示例(进程间同步)

例子:父子进程使用信号量同步输出

#include <stdio.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <unistd.h>
#include <sys/wait.h>union semun {int val;
};int main(){key_t key = ftok(".", 123);int semid = semget(key, 1, IPC_CREAT | 0666);// 初始化信号量0union semun sem_union;sem_union.val = 0;semctl(semid, 0, SETVAL, sem_union);pid_t pid = fork();if (pid == 0) {// 子进程printf("子进程执行完毕\n");struct sembuf sb = {0, 1, 0}; // v操作semop(semid, &sb, 1);exit(0);} else {// 父进程等待子进程完成struct sembuf sb = {0, -1, 0}; // p操作semop(semid, &sb, 1);printf("父进程检测到子进程已完成,继续执行\n");semctl(semid, 0, IPC_RMID); // 删除信号量wait(NULL);}return 0;
}

3.5 信号量使用中的常见注意事项

问题原因或建议解决方式
死锁同步顺序不一致,需避免循环等待
忘记释放资源异常退出未执行 V 操作,建议设置信号处理
IPC 对象未清理(内核残留)使用 ipcs 查看,用 ipcrm 删除
并发性能瓶颈使用共享内存 + 原子操作优化性能

生产环境中更推荐 POSIX 信号量

4,POSIX 信号量

POSIX信号量是基于POSIX标准定义的一种同步机制,支持:

        命令信号量(适用于进程间)

        匿名信号量(适用于线程间或共享内存中的进程)

与System V不同,POSIX信号量接口更贴近现代C编程,支持资源释放自动化(通过sem_close, sem_unlink)。

4.1 POSIX信号量头文件与链接方式

#include <semaphore.h> // 所有POSIX信号量接口
#include <fcntl.h>      // O_CREAT 等
#include <sys/stat.h>   // S_IRUSR等编译时需要链接 -pthread或-lrt
gcc demo.c -o demo -pthread

4.2 POSIX信号量类型

类型适用范围创建方式
命名信号量多进程共享sem_open
匿名信号量多线程或共享内存sem_init

4.3 常用函数接口(详细对照表)

函数名用法描述
sem_init初始化匿名信号量
sem_destroy销毁匿名信号量(与 sem_init 配合)
sem_open打开或创建命名信号量
sem_close关闭命名信号量(与 sem_open 配合)
sem_unlink删除命名信号量名称
sem_waitP 操作,等待(阻塞直到信号量值 > 0)
sem_trywait非阻塞的 P 操作
sem_postV 操作,释放
sem_getvalue获取当前信号量的值

4.4 使用命名信号量(适用于进程间)

4.4.1 创建和初始化

sem_t *sem = sem_open("/mysem", o_CREAT, 0666, 1);/mysem:信号量名称(必须以 / 开头)
0666: 权限
1: 初始值

4.4.2 使用信号量(同步)

sem_wait(sem);  // p操作(阻塞)

sem_post(sem); // v操作(释放)

4.4.3 关闭与释放资源

sem_close(sem);  // 关闭描述符

sem_unlink("/mysem"); // 从系统中删除该命名信号量

4.4.4 示例:两个进程同步输出

父进程代码(writer.c)

#include <stdio.h>
#include <semaphore.h>
#include <fcntl.h>
#include <unistd.h>int main() {sem_t *sem = sem_open("/syncsem", O_CREAT, 0666, 0);printf("父进程准备工作完成,等待子进程信号。。。\n");sem_wait(sem);   // 等待子进程完成任务printf("父进程收到子进程信号,继续执行。。。\n");sem_close(sem);sem_unlink("/syncsem");return 0;
}

子进程代码(reader.c)

#include <stdio.h>
#include <semaphore.h>
#include <fcntl.h>
#include <unistd.h>
#included <stdlib.h>int main() 
{sem_t *sem = sem_open("/syncsem", 0);sleep(2); // 模拟处理printf("子进程完成任务,通知父进程。。。\n");sem_post(sem); // 释放信号量sem_close(sem);return 0;
}

4.5 使用匿名信号量(适用于线程或内存共享)

4.5.1 初始化匿名信号量

sem_t sem;
sem_init(&sem, 0, 1); // 第二参数为0表示线程间使用;为1表示可用于进程间(共享内存中)

4.5.2 使用方式

sem_wait(&sem);
sem_post(&sem);

4.5.3 销毁信号量

sem_destory(&sem);

4.5.4 示例:线程互斥访问共享资源

#include <pthread.h>
#include <semaphore.h>
#include <stdio.h>
#include <unsitd.h>sem_t sem;void *thread_func(void *arg) {sem_wait(&sem);printf("线程 %ld 正在访问共享资源\n", pthread_self());sleep(1);printf("线程 %ld 释放共享资源\n", pthread_self());sem_post(&sem);return;
}int main()
{pthread_t t1, t2;sem_init(&sem, 0, 1); // 匿名信号量,线程间使用pthread_create(&t1, NULL, thread_func, NULL);pthread_create(&
http://www.xdnf.cn/news/879661.html

相关文章:

  • uniapp实现的简约美观的星级评分组件
  • uniapp图片文档预览
  • PHP 8.5 即将发布:管道操作符、强力调试
  • springboot mysql/mariadb迁移成oceanbase
  • 基于Java(SpringBoot、Mybatis、SpringMvc)+MySQL实现(Web)小二结账系统
  • 【图片识别改名】如何批量将图片按图片上文字重命名?自动批量识别图片文字并命名,基于图片文字内容改名,WPF和京东ocr识别的解决方案
  • 【SSM】SpringMVC学习笔记7:前后端数据传输协议和异常处理
  • 阿里云事件总线 EventBridge 正式商业化,构建智能化时代的企业级云上事件枢纽
  • 【Spark征服之路-2.2-安装部署Spark(二)】
  • 力扣LeetBook数组和字符串--二维数组
  • 【无标题】路径着色问题的革命性重构:拓扑色动力学模型下的超越与升华
  • 网络测试实战:金融数据传输的生死时速
  • C++学习-入门到精通【14】标准库算法
  • C++11实现TCP网络通讯服务端处理逻辑简化版
  • ARM处理器工作模式
  • MCP通信方式之Streamable HTTP
  • ZooKeeper 安装教程(Windows + Linux 双平台)
  • Redis 安装配置和性能优化
  • 【bug】Error: /undefinedfilename in (/tmp/ocrmypdf.io.9xfn1e3b/origin.pdf)
  • 仓库拉下ssm项目配置启动
  • Java 高频面试题场景(四):社区老年大学在线学习平台系统
  • Android四大组件通讯指南:Kotlin版组件茶话会
  • 新能源汽车智慧充电桩管理方案:新能源充电桩散热问题及消防安全监管方案
  • 6.5本日总结
  • 【设计模式】门面/外观模式
  • Angular报错:cann‘t bind to ngClass since it is‘t a known property of div
  • Spring Boot 缓存注解详解:@Cacheable、@CachePut、@CacheEvict(超详细实战版)
  • Monorepo架构: Nx Cloud 扩展能力与缓存加速
  • [华为eNSP] OSPF综合实验
  • 在不同型号的手机或平板上后台运行Aidlux