Linux学习笔记

Linux学习笔记

Linux系统相关

GCC(预编译 编译 汇编 链接) G++(多链接过程)

-o 编译
-g 开启gdb调试

Makefile

文件描述符

GDB调试

编译语句后加 -g

功能用法
运行到第一个断点run
开始运行(第一行)start
插入断点b/break 行号/函数名
删除断点delete 断点编号
删除断点clear 代码内行号
禁用断点disable
查看已设置断点info break

Linux多进程开发

进程

fork新建进程 exec函数族

父子进程

孤儿进程 僵尸进程

wait(进程回收,阻塞) waitpid(进程回收,可不阻塞)

进程间通信

匿名管道 有名管道 内存映射(文件)共享内存

signal信号,信号捕捉

守护进程(退父进程,开新会话,清umask,改工作目录,关描述符,使描述符指/dev/null)

  • 执行一个 fork(),退出父进程,子进程继续执行。
  • 子进程调用 setsid() 开启新会话。
  • 清除进程的 umask 以确保当守护进程创建文件和目录时拥有所需的权限。
  • 修改进程的当前工作目录,通常会改为根目录(/)。
  • 关闭守护进程从其父进程继承而来的所有打开着的文件描述符。
  • 在关闭了文件描述符0(标准输入)、1(标准输出)、2(标准错误)之后,守护进程通常会打开/dev/null 并使用dup2()
  • 使所有这些描述符指向这个设备。
  • 核心业务逻辑

Linux多线程开发

常用语法(头文件 pthread.h)

#include<pthread.h>

回收子进程 pthread_join

	int pthread_join(pthread_t thread, void **retval);

功能
和一个已经终止的线程进行连接
回收子线程的资源
这个函数是阻塞函数,调用一次只能回收一个子线程
一般在主线程中使用
参数
thread:需要回收的子线程的ID
retval: 接收子线程退出时的返回值
返回值
0 : 成功
非0 : 失败,返回的错误号
线程分离 pthread_detach

	int pthread_detach(pthread_t thread);

功能
分离一个线程。
被分离的线程在终止的时候,会自动释放资源返回给系统。
非阻塞。
参数
thread:需要分离的线程的ID
返回值
成功:0
失败:返回错误号
注意
1.不能多次分离,会产生不可预料的行为。
2.不能去连接一个已经分离的线程,会报错。

取消线程 pthread_cancel

    int pthread_cancel(pthread_t thread);

功能
取消线程(让线程终止)
取消某个线程,可以终止某个线程的运行,
但是并不是立马终止,而是当子线程执行到一个取消点,线程才会终止。

取消点:系统规定好的一些系统调用,我们可以粗略的理解为从用户区到内核区的切换,这个位置称之为取消点。
参数
thread:需要分离的线程的ID

互斥锁

保证线程安全
一旦线程锁定互斥量,随即成为该互斥量的所有者,只有所有者才能给互斥量解锁。一般情
况下,对每一共享资源(可能由多个相关变量组成)会使用不同的互斥量,每一线程在访问
同一资源时将采用如下协议:

  1. 针对共享资源锁定互斥量
  2. 访问共享资源
  3. 对互斥量解锁
互斥量的类型 pthread_mutex_t

互斥量相关函数

int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);
        - 初始化互斥量
        - 参数 :
            - mutex : 需要初始化的互斥量变量
            - attr : 互斥量相关的属性,NULL
        - restrict : C语言的修饰符,被修饰的指针,不能由另外的一个指针进行操作。
            pthread_mutex_t *restrict mutex = xxx;
            pthread_mutex_t * mutex1 = mutex;

    int pthread_mutex_destroy(pthread_mutex_t *mutex);
        - 释放互斥量的资源

    int pthread_mutex_lock(pthread_mutex_t *mutex);
        - 加锁,阻塞的,如果有一个线程加锁了,那么其他的线程只能阻塞等待

    int pthread_mutex_trylock(pthread_mutex_t *mutex);
        - 尝试加锁,如果加锁失败,不会阻塞,会直接返回。

    int pthread_mutex_unlock(pthread_mutex_t *mutex);
        - 解锁

读写锁

读写锁的特点:

  1. 如果有其它线程读数据,则允许其它线程执行读操作,但不允许写操作。
  2. 如果有其它线程写数据,则其它线程都不允许读、写操作。
  3. 写是独占的,写的优先级高。

生产者消费者模型

条件变量 pthread_cond_t

条件变量的类型 pthread_cond_t
创建销毁进程

    //创建线程
   int pthread_cond_init(pthread_cond_t *restrict cond, const pthread_condattr_t *restrict attr);
   
   //销毁线程
   int pthread_cond_destroy(pthread_cond_t *cond);
	//等待,调用该函数,线程会阻塞
    int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex);
    
    //等待固定时间,调用了这个函数,线程会阻塞,直到指定的时间结束
    int pthread_cond_timedwait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex, const struct timespec *restrict abstime);
    
    //唤醒一个或者多个等待的线程
    int pthread_cond_signal(pthread_cond_t *cond);
    
    //唤醒所有的等待的线程 
    int pthread_cond_broadcast(pthread_cond_t *cond);

信号量 sem_t(可计数,计数为0阻塞)

int sem_wait(sem_t *sem);
    - 对信号量加锁,调用一次对信号量的值-1,如果值为0,就阻塞

int sem_post(sem_t *sem);
    - 对信号量解锁,调用一次对信号量的值+1

Linux网络编程

C/S结构(服务器 - 客户机)

服务器 - 客户机,即 Client - Server(C/S)结构。C/S 结构通常采取两层结构。
服务器
数据的管理
提供信息供人访问

客户机
与用户交互
访问别人信息
优点

  1. 能充分发挥客户端 PC 的处理能力,很多工作可以在客户端处理后再提交给服务器,所以 C/S 结构客户端响应速度快;
  2. 操作界面漂亮、形式多样,可以充分满足客户自身的个性化要求;
  3. C/S 结构的管理信息系统具有较强的事务处理能力,能实现复杂的业务流程;
  4. 安全性较高,C/S 一般面向相对固定的用户群,程序更加注重流程,它可以对权限进行多层次校验,提供了更安全的存取模式,对信息安全的控制能力很强,一般高度机密的信息系统采用 C/S 结
    构适宜。
    缺点
  5. 客户端需要安装专用的客户端软件。首先涉及到安装的工作量,其次任何一台电脑出问题,如病毒、硬件损坏,都需要进行安装或维护。系统软件升级时,每一台客户机需要重新安装,其维护和升级成本非常高;
  6. 对客户端的操作系统一般也会有限制,不能够跨平台。
B/S结构(浏览器/服务器模式)

B/S 结构(Browser/Server,浏览器/服务器模式),是 WEB 兴起后的一种网络结构模式,WEB浏览器是客户端最主要的应用软件。这种模式统一了客户端,将系统功能实现的核心部分集中到服务器上,简化了系统的开发、维护和使用。
优点
B/S 架构最大的优点是总体拥有成本低、维护方便、 分布性强、开发简单,可以不用安装任何专门的软件就能实现在任何地方进行操作,客户端零维护,系统的扩展非常容易,只要有一台能上网的电脑就能使用。
缺点

  1. 通信开销大、系统和数据的安全性较难保障; 2. 个性特点明显降低,无法实现具有个性化的功能要求;
  2. 协议一般是固定的:http/https
  3. 客户端服务器端的交互是请求-响应模式,通常动态刷新页面,响应速度明显降低。
MAC地址(网络适配器、网卡)

其拥有 MAC 地址,属于 OSI 模型的第 2 层,它使得用户可以通过电缆或无线相互连接。每一个网卡都有一个被称为 MAC 地址的独一无二的 48位 串行号。

网卡主要功能
  1. 数据的封装与解封装
  2. 链路管理
  3. 数据编码与译码
IP地址

IP 协议是为计算机网络相互连接进行通信而设计的协议。在因特网中,它是能使连接到网上的所有计算机网络实现相互通信的一套规则,规定了计算机在因特网上进行通信时应当遵守的规则。

类别最大网络数IP地址范围单个网段最大主机数 私有IP地址范围
A126(2^7-2)1.0.0.1-126.255.255.2541677721410.0.0.0-10.255.255.255
B16384(2^14)128.0.0.1-191.255.255.25465534172.16.0.0-172.31.255.255
C2097152(2^21)192.0.0.1-223.255.255.254254192.168.0.0-192.168.255.255
子网掩码(网络掩码、地址掩码、子网络遮罩)

作用
将某个 IP 地址划分成 网络地址主机地址 两部分。
必须结合 IP 地址一起使用。

端口

虚拟端口和物理端口
端口号范围是从 0 到 65535(2^16-1)
端口类型
1.周知端口(Well Known Ports 知名端口 公认端口 者常用端口)
周知端口是众所周知的端口号,范围从 0 到 1023,它们紧密绑定于一些特定的服务。
例如 :
80 端口分配给 WWW 服务
21 端口分配给 FTP 服务
23 端口分配给Telnet服务
2.注册端口(Registered Ports)
端口号从:1024 到 49151,它们松散地绑定于一些服务,分配给用户进程或应用程序,用户选择安装的一些应用程序,这些端口在没有被服务器资源占用的时候,可以用用户端动态选用为源端口。
3.动态端口 / 私有端口(Dynamic Ports / Private Ports)
端口号: 49152 到 65535。动态分配某种服务。

网络模型

OSI模型 TCP/IP模型

在这里插入图片描述
在这里插入图片描述

应用层常见协议
FTP协议(File Transfer Protocol 文件传输协议)
HTTP协议(Hyper TextTransfer Protocol 超文本传输协议)
NFS(Network File System 网络文件系统)
传输层常见协议
TCP协议(Transmission Control Protocol 传输控制协议)
UDP协议(User Datagram Protocol 用户数据报协议)
网络层 常见协议
IP 协议(Internet Protocol 因特网互联协议)
ICMP 协议(Internet Control Message Protocol 因特网控制报文协议)IGMP 协议(Internet Group Management Protocol 因特网组管理协议)
网络接口层 常见协议
ARP协议(Address Resolution Protocol 地址解析协议)
RARP协议(Reverse Address Resolution Protocol 反向地址解析协议)
UDP协议
在这里插入图片描述
arp协议:通过ip地址查找mac地址
rarp协议

TCP 协议

TCP头部结构
在这里插入图片描述

TCP流程
在这里插入图片描述

三次握手

发生在客户端连接的时候,当调用connect(),底层会通过TCP协议进行三次握手。
目的:保证双方互相之间建立连接。
client:客户端
server:服务器端
在这里插入图片描述

TCP滑动窗口(Sliding window)

在这里插入图片描述
mss:Maximum Segment Size(一条数据最大的数据量)
win:滑动窗口

  1. 客户端向服务器发起连接,客户端的滑动窗口是4096,一次发送的最大数据量是11460
  2. 服务器接收连接情况,告诉客户端服务器的窗口大小是6144,一次发送的最大数据量是1024
  3. 第三次握手
  4. 4-9客户端连续分次给服务器发送了共6k数据,每次1k
  5. 第10次,服务器告诉客户端:收到 6k 数据,存储在缓冲区中,缓冲区数据已经处理了 2k,窗口大小是 2k
  6. 第11次,服务器告诉客户端:收到 6k 数据,存储在缓冲区中,缓冲区数据已经处理了 4k,窗口大小是 4k
  7. 第12次,客户端给服务器发送了 1k 的数据
  8. 第13次,客户端主动和服务器断开连接,并且给服务器发送了 1k 数据。
  9. 第14次,服务器回复ACK 8194.a:同意断开连接的请求 b:告诉客户端已经接受到方才发的 2k 的数据 c:滑动窗口 2k
  10. 第15、16次,通知滑动窗口的大小
  11. 第17次,第三次挥手,服务器端给客户端发送FIN,请求断开连接
  12. 第18次,第四次挥手,客户端同意了服务器端的断开请求
四次挥手

发生在断开连接时,在程序中当调用了close()会使用TCP协议进行四次挥手。
客户端和服务器端都可以主动发起断开连接,谁先调用close()谁就是发起。
需要双向断开
在这里插入图片描述

输入网址到网页显示的整个流程
  1. DNS解析
    浏览器缓存 --> 操作系统缓存 --> 路由器缓存–>本地(ISP)域名服务器缓存 --> 根域名服务器
  2. 进行TCP连接
    得到了IP以后,向服务器发送TCP连接,TCP连接经过三次握
  3. 浏览器发送HTTP请求
    方式为GET 包含了主机(Host)、用户代理(User-Agent)
  4. 服务器处理请求
    解析请求(读请求头),生成一个响应头和具体响应内容。传回来一个响应头和一个响应,响应头告诉了浏览器一些必要的信息
  5. 浏览器解析渲染页面
    (1) 浏览器显示HTML
    服务器返回响应后,浏览器读取响应头,然后解析响应并在逐步在页面上显示出来。
    (2) 浏览器向服务器发送请求获取嵌入在HTML中的对象
    在浏览器显示HTML时,打开网页过程中,主页(index)页面框架传送过来以后,浏览器还会因页面上的静态资源多次发起连接请求,需要获取嵌入在HTML中。
    静态的文件一般会从CDN中去取,CDN根据请求获取资源的时候可能还会用到负载均衡。
    (3) 浏览器发送异步(AJAX)请求
    对于动态请求,动态网页等必须要从服务器获取。静态内容,浏览器会进行缓存。动态内容,不会进行缓存。对于动态请求,Nginx可能会专门设置一些服务器用来处理这些访问动态页面的请求。
  6. 关闭TCP连接
    当数据完成请求到返回的过程之后,根据Connection的Keep-Alive属性选择是否断开TCP连接,HTTP/1.1支持同一个TCP多个请求,1.0版本完成一次请求就断开。
TCP UDP 对比

TCP 和 UDP 属于 传输层的协议
UDP:用户数据报协议,面向无连接,可以单播,多播,广播, 面向数据报,不可靠
TCP:传输控制协议,面向连接的,可靠的,基于字节流,仅支持单播传输

UDPTCP
是否创建连接无连接面向连接
是否可靠不可靠可靠的
连接的对象个数一对一、一对多、多对一、多对多支持一对一
传输的方式面向数据报面向字节流
首部开销8个字节最少20个字节
适用场景实时应用(视频会议,直播)可靠性高的应用(文件传输)
TPC 通信流程

服务器端(被动接受连接的角色)

  1. 创建一个用于监听的套接字
    - 监听:监听有客户端的连接
    - 套接字:这个套接字其实就是一个文件描述符
  2. 将这个监听文件描述符和本地的IP和端口绑定(IP和端口就是服务器的地址信息)
    - 客户端连接服务器的时候使用的就是这个IP和端口
  3. 设置监听,监听的fd开始工作
  4. 阻塞等待,当有客户端发起连接,解除阻塞,接受客户端的连接,会得到一个和客户端通信的套接字 (fd)
  5. 通信
    - 接收数据
    - 发送数据
  6. 通信结束,断开连接

客户端

  1. 创建一个用于通信的套接字(fd)
  2. 连接服务器,需要指定连接的服务器的 IP 和 端口
  3. 连接成功了,客户端可以直接和服务器通信
    - 接收数据
    - 发送数据
  4. 通信结束,断开连接
UDP 通信流程

在这里插入图片描述

HTTP 和 HTTPS 协议区别

1、HTTPS协议需要到证书颁发机构(Certificate Authority,简称CA)申请证书,一般免费证书很少,需要交费。
2、HTTP是超文本传输协议,信息明文传输,HTTPS则是具有安全性的SSL加密传输协议。
3、HTTP和HTTPS使用的是完全不同的连接方式,使用的端口也不一样,前者是80,后者是443。
4、HTTP的连接很简单,是无状态的。
5、HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,要比HTTP协议安全。
HTTPS优点

  • 数据完整性:内容传输经过完整性校验
  • 数据隐私性:内容经过对称加密,每个连接生成一个唯一的加密密钥
  • 身份认证:第三方无法伪造服务端(客户端)身份

其中,数据完整性和隐私性由TLS Record Protocol保证,身份认证由TLS Handshaking Protocols实现。

socket 通信

TCP通信并发

多线程或者多进程解决。
思路:
1. 一个父进程,多个子进程
2. 父进程:负责等待并接受客户端的连接
3. 子进程:完成通信,接受一个客户端连接,就创建一个子进程用于通信

I/O多路复用(I/O多路转接)

I/O 多路复用使得程序能同时监听多个文件描述符,能够提高程序的性能,Linux 下实现 I/O 多路复用的系统调用主要有 select、poll 和 epoll

select

主旨思想:

  1. 首先要构造一个关于文件描述符的列表,将要监听的文件描述符添加到该列表中。
  2. 调用一个系统函数,监听该列表中的文件描述符,直到这些描述符中的一个或者多个进行I/O
    操作时,该函数才返回。
    a.这个函数是阻塞
    b.函数对文件描述符的检测的操作是由内核完成的
  3. 在返回时,它会告诉进程有多少(哪些)描述符要进行I/O操作。

缺点:

  1. 每次调用select,都需要把fd集合从用户态拷贝到内核态,这个开销在fd很多时会很大
  2. 同时每次调用select都需要在内核遍历传递进来的所有fd,这个开销在fd很多时也很大
  3. select支持的文件描述符数量太小了,默认是1024
  4. fds集合不能重用,每次都需要重置
poll(改进select)
  1. 每次调用,都需要把fd集合从用户态拷贝到内核态,这个开销在fd很多时会很大
  2. 同时每次调用都需要在内核遍历传递进来的所有fd,这个开销在fd很多时也很大
epoll

内核区创建eventpoll,利用红黑树双链表优化。
返回就绪的文件描述符(返回数据较select、epoll少)。
工作模式
LT模式(水平触发 默认)
支持阻塞和非阻塞
只要有就绪就通知,哪怕不做操作

假设委托内核检测读事件 -> 检测fd的读缓冲区
读缓冲区有数据 - > epoll检测到了会给用户通知
a. 用户不读数据,数据一直在缓冲区,epoll 会一直通知
b. 用户只读了一部分数据,epoll会通知
c. 缓冲区的数据读完了,不通知

ET模式(边沿触发)
仅支持非阻塞
同一组数据只通知一次,哪怕未读完
效率较LT高

假设委托内核检测读事件 -> 检测fd的读缓冲区
读缓冲区有数据 - > epoll检测到了会给用户通知
a.用户不读数据,数据一致在缓冲区中,epoll下次检测的时候就不通知了
b.用户只读了一部分数据,epoll不通知
c.缓冲区的数据读完了,不通知

UDP 通信流程

在这里插入图片描述

高并发项目

在这里插入图片描述

模块功能
I/O 处理单元处理客户连接,读写网络数据
逻辑单元业务进程或线程
网络存储单元数据库、文件或缓存
请求队列各单元之间的通信方式

同步 异步

两种高效的事件处理模式

Reactor:通常同步处理

使用同步 I/O(以 epoll_wait 为例)实现的 Reactor 模式的工作流程是:

  1. 主线程往 epoll 内核事件表中注册 socket 上的读就绪事件。
  2. 主线程调用 epoll_wait 等待 socket 上有数据可读。
  3. 当 socket 上有数据可读时, epoll_wait 通知主线程。主线程则将 socket 可读事件放入请求队列。
  4. 睡眠在请求队列上的某个工作线程被唤醒,它从 socket 读取数据,并处理客户请求,然后往 epoll
    内核事件表中注册该 socket 上的写就绪事件。
  5. 当主线程调用 epoll_wait 等待 socket 可写。
  6. 当 socket 可写时,epoll_wait 通知主线程。主线程将 socket 可写事件放入请求队列。
  7. 睡眠在请求队列上的某个工作线程被唤醒,它往 socket 上写入服务器处理客户请求的结果。
    在这里插入图片描述
Proactor:通常异步处理

Proactor 模式将所有 I/O 操作都交给主线程和内核来处理(进行读、写),工作线程仅仅负责业务逻
辑。使用异步 I/O 模型(以 aio_read 和 aio_write 为例)实现的 Proactor 模式的工作流程是:

  1. 主线程调用 aio_read 函数向内核注册 socket 上的读完成事件,并告诉内核用户读缓冲区的位置,
    以及读操作完成时如何通知应用程序(这里以信号为例)。
  2. 主线程继续处理其他逻辑。
  3. 当 socket 上的数据被读入用户缓冲区后,内核将向应用程序发送一个信号,以通知应用程序数据
    已经可用。
  4. 应用程序预先定义好的信号处理函数选择一个工作线程来处理客户请求。工作线程处理完客户请求
    后,调用 aio_write 函数向内核注册 socket 上的写完成事件,并告诉内核用户写缓冲区的位置,以
    及写操作完成时如何通知应用程序。
  5. 主线程继续处理其他逻辑。
  6. 当用户缓冲区的数据被写入 socket 之后,内核将向应用程序发送一个信号,以通知应用程序数据
    已经发送完毕。
  7. 应用程序预先定义好的信号处理函数选择一个工作线程来做善后处理,比如决定是否关闭 socket。
    Proactor 模式的工作流程:
    在这里插入图片描述
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值