文章目录
目录
文章目录
前言
一、前后台进程
1. 前台进程 (Foreground Process)
2. 后台进程 (Background Process)
3. 前后台进程的切换
4. 关键命令和操作
5. 注意事项
6. 信号处理
二、守护进程
1. 守护进程的核心特点
2. 常见守护进程示例
3.接口介绍
1、 fork()
2. setsid()
3. chdir()
4. umask()
5. close()
4. 如何创建守护进程?
步骤解释:
5. 管理守护进程的工具
6. 守护进程 vs 前后台进程
7. 注意事项
总结
三、tcp连接机制
1. 三次握手(Three-Way Handshake)
步骤:
为什么需要三次握手?
2. 四次挥手(Four-Way Handshake)
步骤:
为什么需要四次挥手?
TIME_WAIT状态
3. 全双工通信(Full-Duplex)
特点:
示例:
总结
四、网络通信中的序列及反序列
一、序列化的作用
二、反序列化的作用
三、应用场景
四、常见序列化技术
五、安全问题
总结
总结
前言
Linux——网络(tcp)-CSDN博客
一、前后台进程
1. 前台进程 (Foreground Process)
-
定义:默认情况下,用户在终端启动的进程会占用终端输入/输出,称为前台进程。
-
特点:
-
进程运行时,终端被“锁定”,用户必须等待进程结束才能输入新命令。
-
进程的输出直接显示在终端,用户可以通过键盘输入与进程交互(如输入参数或终止信号)。
-
-
示例:
# 启动一个前台进程(例如 ping 命令) ping example.com
2. 后台进程 (Background Process)
-
定义:进程在后台运行,不占用终端输入/输出,用户可继续使用终端执行其他命令。
-
特点:
-
终端不会被阻塞,用户可以继续输入命令。
-
进程的输出仍可能显示在终端(可能干扰当前操作),建议重定向输出到文件。
-
后台进程的生存期可能与终端会话绑定(若终端关闭,后台进程可能被终止,需使用
nohup
或disown
避免)。
-
-
启动方式:
# 在命令末尾添加 & 符号 ping example.com &
3. 前后台进程的切换
-
将前台进程放到后台:
-
按下
Ctrl + Z
暂停当前前台进程。 -
输入
bg
命令将暂停的进程转为后台运行。
-
-
查看后台进程列表:
jobs -l
-
将后台进程切换到前台:
fg %<job_number> # 例如 fg %1
4. 关键命令和操作
命令 | 作用 |
---|---|
command & | 直接启动后台进程 |
Ctrl + Z | 暂停当前前台进程 |
bg | 将最近暂停的进程转为后台运行 |
fg %n | 将后台进程 n 切换到前台 |
jobs -l | 列出所有后台/暂停的进程及其编号 |
nohup command & | 启动后台进程,终端关闭后仍存活 |
disown | 断开进程与终端的关联 |
5. 注意事项
-
输出干扰:后台进程的输出可能混杂在终端中,建议使用输出重定向:
command > output.log 2>&1 &
-
终端关闭问题:默认情况下,终端退出时会终止所有关联的后台进程。若需持久化运行:
-
使用
nohup
:nohup command &
-
使用
disown
:command & disown %1 # 脱离终端关联
-
使用终端复用工具(如
tmux
或screen
)。
-
6. 信号处理
-
前台进程可直接接收终端信号(如
Ctrl + C
发送SIGINT
,Ctrl + Z
发送SIGTSTP
)。 -
后台进程默认不接收键盘输入信号,但可能收到终端关闭时的
SIGHUP
信号(需通过nohup
或disown
避免)。
通过灵活使用前后台进程,可以高效管理终端任务,尤其适合需要长时间运行或并行操作的情景。
在 Linux 中,**守护进程(Daemon Process)**是一种特殊的后台进程,通常用于长期运行的服务或任务(如 Web 服务器、数据库服务等)。它完全脱离终端控制,独立于用户会话,生命周期与系统运行一致。以下是守护进程的特点及示例:
二、守护进程
1. 守护进程的核心特点
-
脱离终端:不依赖于任何终端,即使启动它的终端关闭,守护进程依然运行。
-
无交互界面:不与用户直接交互,通常以静默模式运行。
-
长期运行:持续驻留内存,提供系统级服务。
-
独立环境:
-
工作目录通常设置为根目录(
/
),避免占用挂载点。 -
文件权限掩码(
umask
)设为0
,确保文件操作权限可控。 -
关闭不必要的文件描述符(如标准输入、输出、错误流)。
-
2. 常见守护进程示例
-
系统服务:
-
sshd
:SSH 远程登录服务。 -
nginx
/apache
:Web 服务器。 -
cron
:定时任务调度服务。
-
-
自定义守护进程:
-
日志监控脚本。
-
自动化备份服务。
-
3.接口介绍
1、 fork()
- 功能:用于创建一个新的进程,这个新进程是调用进程(父进程)的副本,被称为子进程。在调用
fork()
之后,父进程和子进程会从fork()
调用处开始继续执行,通过fork()
的返回值来区分是父进程还是子进程。 - 返回值:
- 在父进程中,返回子进程的进程 ID(PID),是一个正整数。
- 在子进程中,返回 0。
- 如果出错,返回 -1。
- 示例代码:
#include <stdio.h>
#include <unistd.h>int main() {pid_t pid = fork();if (pid < 0) {perror("fork");return 1;} else if (pid == 0) {// 子进程printf("This is child process, PID: %d\n", getpid());} else {// 父进程printf("This is parent process, child PID: %d\n", pid);}return 0;
}
2. setsid()
- 功能:调用
setsid()
的进程会创建一个新的会话,成为新会话的会话首进程,同时也会成为一个新进程组的组长进程,并且脱离原有的控制终端,从而使进程在后台独立运行。 - 返回值:
- 成功时,返回新会话的会话 ID。
- 失败时,返回 -1。
- 示例代码:
#include <stdio.h>
#include <unistd.h>int main() {pid_t pid = fork();if (pid < 0) {perror("fork");return 1;} else if (pid == 0) {// 子进程pid_t sid = setsid();if (sid < 0) {perror("setsid");return 1;}printf("New session ID: %d\n", sid);}return 0;
}
3. chdir()
- 功能:用于改变当前进程的工作目录。在创建守护进程时,通常会将工作目录更改为根目录
/
或其他合适的目录,以避免因原工作目录被卸载等情况导致进程出现问题。 - 返回值:
- 成功时,返回 0。
- 失败时,返回 -1。
- 示例代码:
#include <stdio.h>
#include <unistd.h>int main() {if (chdir("/") == -1) {perror("chdir");return 1;}printf("Working directory changed to root.\n");return 0;
}
4. umask()
- 功能:用于设置文件创建掩码,它会影响后续创建文件和目录的默认权限。通过设置合适的掩码,可以确保守护进程创建的文件和目录具有正确的权限。
- 返回值:返回之前的文件创建掩码。
- 示例代码:
#include <stdio.h>
#include <sys/stat.h>int main() {mode_t old_umask = umask(0);printf("Old umask: %o\n", old_umask);return 0;
}
5. close()
- 功能:用于关闭文件描述符。在创建守护进程时,通常会关闭标准输入(文件描述符 0)、标准输出(文件描述符 1)和标准错误输出(文件描述符 2),因为守护进程在后台运行,不需要与终端进行交互。
- 返回值:
- 成功时,返回 0。
- 失败时,返回 -1。
- 示例代码:
#include <stdio.h>
#include <unistd.h>int main() {close(0);close(1);close(2);printf("Standard file descriptors closed.\n"); // 这行不会有输出,因为标准输出已关闭return 0;
}
4. 如何创建守护进程?
以下是一个用 Python 编写的简单守护进程示例,实现每隔 5 秒写入日志的功能:
#pragma once#include <iostream>
#include <cstdlib>
#include <unistd.h>
#include <signal.h>
#include <string>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>const std::string nullfile = "/dev/null";void Daemon(const std::string &cwd = "")
{// 1. 忽略其他异常信号signal(SIGCLD, SIG_IGN);signal(SIGPIPE, SIG_IGN);signal(SIGSTOP, SIG_IGN);// 2. 将自己变成独立的会话if (fork() > 0)exit(0);setsid();// 3. 更改当前调用进程的工作目录if (!cwd.empty())chdir(cwd.c_str());// 4. 标准输入,标准输出,标准错误重定向至/dev/nullint fd = open(nullfile.c_str(), O_RDWR);if(fd > 0){dup2(fd, 0);dup2(fd, 1);dup2(fd, 2);close(fd);}
}
步骤解释:
代码中有注释
5. 管理守护进程的工具
-
systemd(现代 Linux 系统):
# 创建服务单元文件(如 /etc/systemd/system/mydaemon.service) [Unit] Description=My Custom Daemon After=network.target[Service] ExecStart=/usr/bin/python3 /path/to/mydaemon.py Restart=always[Install] WantedBy=multi-user.target# 启动并启用守护进程 sudo systemctl start mydaemon sudo systemctl enable mydaemon
-
sysvinit(旧系统):通过
init.d
脚本管理。
6. 守护进程 vs 前后台进程
特性 | 前台进程 | 后台进程 | 守护进程 |
---|---|---|---|
依赖终端 | ✔️ 是(锁定终端) | ❌ 否(但关联终端) | ❌ 完全脱离终端 |
生命周期 | 终端关闭则终止 | 终端关闭可能终止 | 独立运行,与系统共存亡 |
典型用途 | 临时任务 | 临时后台任务 | 系统/网络服务 |
输出交互 | 直接显示在终端 | 可能干扰终端 | 无输出或重定向到日志文件 |
启动方式 | 直接运行 | command & | systemd /nohup /自定义 |
7. 注意事项
-
日志管理:守护进程应记录日志(如通过
syslog
或自定义文件),方便排查问题。 -
资源泄漏:长期运行的守护进程需注意内存/文件描述符泄漏。
-
信号处理:需正确处理
SIGTERM
、SIGHUP
等信号,实现优雅退出或配置重载。
总结
守护进程是 Linux 系统的“幕后工作者”,用于实现核心服务或后台任务。通过脱离终端、配置独立环境,它们能稳定地为系统提供支持。实际开发中,可直接使用 systemd
等工具管理,避免重复造轮子。
三、tcp连接机制
1. 三次握手(Three-Way Handshake)
三次握手用于建立TCP连接,确保双方确认彼此的发送和接收能力正常,并同步初始序列号(Sequence Number)。
步骤:
-
SYN(同步报文)
-
客户端向服务器发送
SYN=1
报文,并携带初始序列号seq=x
,表示请求建立连接。
-
-
SYN-ACK(同步确认报文)
-
服务器收到
SYN
后,回复SYN=1
和ACK=1
报文,确认客户端的序列号(ack=x+1
),并携带自己的初始序列号seq=y
。
-
-
ACK(确认报文)
-
客户端确认服务器的
SYN
,发送ACK=1
报文,ack=y+1
,连接正式建立。
-
为什么需要三次握手?
-
防止历史重复连接的初始化(如旧的延迟
SYN
报文被误认为新请求)。 -
确保双方确认彼此的发送和接收能力正常。
-
同步初始序列号,为后续可靠传输奠定基础。
2. 四次挥手(Four-Way Handshake)
四次挥手用于安全释放TCP连接,确保双方数据完全传输完毕,并允许双向独立关闭。
步骤:
-
FIN(终止报文)
-
主动关闭方(如客户端)发送
FIN=1
报文,seq=u
,表示不再发送数据,但可接收数据。
-
-
ACK(确认报文)
-
被动关闭方(如服务器)回复
ACK=1
,ack=u+1
,确认收到FIN
。
-
-
FIN(终止报文)
-
被动关闭方处理完剩余数据后,发送自己的
FIN=1
报文,seq=v
。
-
-
ACK(确认报文)
-
主动关闭方回复
ACK=1
,ack=v+1
,连接正式关闭。
-
为什么需要四次挥手?
-
TCP是全双工的,需独立关闭两个方向的数据流。
-
被动关闭方可能需要时间处理未发送完的数据,延迟发送自己的
FIN
。
TIME_WAIT状态
主动关闭方在发送最后一个 ACK
后会进入 TIME_WAIT
状态(持续2MSL,即最大报文生存时间),确保:
-
被动关闭方收到最终的
ACK
。 -
防止旧连接的延迟报文干扰新连接。
3. 全双工通信(Full-Duplex)
TCP连接是全双工的,即通信双方可同时、独立地发送和接收数据,互不影响。
特点:
-
双向传输:两端均有独立的发送和接收缓冲区。
-
并行性:发送数据无需等待对方响应(如:上传文件时仍可接收消息)。
-
流量控制:通过滑动窗口机制,独立管理每个方向的数据流速率。
示例:
-
视频通话:双方同时传输音视频数据。
-
HTTP/1.1 Keep-Alive:浏览器和服务器复用同一连接处理多个请求。
总结
机制 | 目的 | 关键点 |
---|---|---|
三次握手 | 建立可靠的双向连接 | 防历史连接、同步序列号、确认双方能力 |
四次挥手 | 安全释放双向连接 | 独立关闭、处理残留数据、TIME_WAIT防报文丢失 |
全双工通信 | 支持双向同时数据传输 | 独立缓冲区、滑动窗口控制、高效并行通信 |
这些机制共同保障了TCP的可靠性、有序性和高效性,成为互联网数据传输的基石。
四、网络通信中的序列及反序列
一、序列化的作用
-
将数据转换为通用格式
-
在发送端,程序中的复杂数据结构(如对象、数组、字典等)无法直接在网络中传输,必须转换成一种标准化的字节流(如 JSON、XML、Protocol Buffers、二进制等)。
-
例如:一个 Python 字典
{"name": "Alice", "age": 30}
会被序列化为 JSON 字符串{"name":"Alice","age":30}
或二进制格式。
-
-
跨平台/跨语言兼容性
-
不同编程语言(如 Python、Java、C++)对数据结构的实现差异较大,序列化后的通用格式可被任何语言解析,确保异构系统间的通信。
-
-
压缩与优化
-
序列化时可通过算法(如 Protocol Buffers、MessagePack)压缩数据体积,减少网络带宽消耗,提升传输效率。
-
-
持久化存储
-
序列化后的数据可保存到文件或数据库(如 Redis 缓存对象),便于后续恢复或传输。
-
二、反序列化的作用
-
重建原始数据结构
-
接收端将收到的字节流还原为程序可操作的原生数据结构。例如将 JSON 字符串反序列化为 Java 对象或 Python 字典。
-
-
数据校验与安全
-
反序列化时可以对数据进行格式校验(如 JSON Schema),防止恶意构造的数据攻击(如反序列化漏洞)。
-
-
支持复杂类型
-
处理嵌套对象、日期、枚举等特殊类型,确保数据完整性(例如将 JSON 中的字符串
"2023-10-01"
转换为Date
对象)。
-
三、应用场景
-
网络通信协议
-
HTTP API:客户端发送 JSON/XML 请求,服务端反序列化为对象处理。
-
RPC(远程过程调用):如 gRPC 使用 Protocol Buffers 序列化数据。
-
消息队列:Kafka、RabbitMQ 传输的消息需序列化。
-
-
分布式系统
-
微服务间通过序列化传递数据(如 Dubbo 使用 Hessian 序列化)。
-
-
缓存与存储
-
Redis 存储对象时需序列化为字符串或二进制。
-
四、常见序列化技术
格式/协议 | 特点 |
---|---|
JSON | 人类可读、跨语言支持,但冗余较多,性能较低。 |
XML | 标签化结构,支持复杂数据,但体积大。 |
Protocol Buffers | 二进制、高效压缩,需预定义 Schema(.proto 文件),适合高性能场景。 |
MessagePack | 二进制,比 JSON 更紧凑,无需 Schema。 |
Avro | 动态 Schema 支持,常用于大数据系统(如 Hadoop)。 |
五、安全问题
-
反序列化漏洞:攻击者构造恶意序列化数据,触发远程代码执行(如 Java 的
ObjectInputStream
漏洞)。 -
防御措施:使用安全协议(如 TLS)、校验数据签名、限制反序列化类白名单。
总结
序列化和反序列化是网络通信的“翻译官”,解决了数据在异构环境中的标准化传输和语义一致性问题,是分布式系统、微服务、实时通信等技术的基础支撑。
总结
在 Linux 中,**守护进程(Daemon Process)**是一种特殊的后台进程,通常用于长期运行的服务或任务(如 Web 服务器、数据库服务等)。它完全脱离终端控制,独立于用户会话,生命周期与系统运行一致。
机制 | 目的 | 关键点 |
---|---|---|
三次握手 | 建立可靠的双向连接 | 防历史连接、同步序列号、确认双方能力 |
四次挥手 | 安全释放双向连接 | 独立关闭、处理残留数据、TIME_WAIT防报文丢失 |
全双工通信 | 支持双向同时数据传输 | 独立缓冲区、滑动窗口控制、高效并行通信 |
这些机制共同保障了TCP的可靠性、有序性和高效性,成为互联网数据传输的基石。
序列化和反序列化是网络通信的“翻译官”,解决了数据在异构环境中的标准化传输和语义一致性问题,是分布式系统、微服务、实时通信等技术的基础支撑。