一、IO进程:IPC
1.标准IO和系统IO的区别
标准文件IO概念:C库中定义的一组用于输入输出的函数
特点
(1)有缓存机制,减少系统调用
(2)围绕文件流举行操作
(3)默认打开三个文件流,stdin、stdout、stderr
(4)只能对普通文件举行操作
系统文件IO概念:系统中的一组用于输入输出的函数
特点
(1)无缓存机制,每次都要系统调用
(2)围绕文件描述符举行操作
(3)默认打开三个文件描述符,0、1、2
(4)可以对恣意类型的文件操作,不能操作目录
| 标准IO
| 文件IO
| 概念
| C库中定义的一组用于输入输出的函数
| posix中定义的一组用于输入输出的函数
| 特点
|
- 有缓冲机制
- 围绕流举行操作,FILE *
- 默认打开三个流: stdin/stdout/stderr
- 只能操作普通类型文件
- 可移植性更强
|
- 没有缓冲机制
- 围绕文件描述符操作,非负整数
- 默认打开三个文件描述符:0/1/2
- 可以操作除了目录以外的任何类型文件
- 可移植性较弱
| 函数
| 打开文件:fopen、freopen
关闭文件:fclose
读文件:fgetc\fgets\fread
写文件:fputc\fputs\fwrite
定位操作:rewind\fseek\ftell
| 打开文件:open
关闭文件:close
读文件:read
写文件:write
定位操作:lseek
|
2.静态库和动态库的区别
静态库和动态库,本质区别是代码被载入时刻不同。
1) 静态库在程序编译时会被毗连到目标代码中。
长处:程序运行时将不再必要该静态库,运行速度更快,移植性更好 ;
缺点:静态库中的代码复制到了程序中,因此体积较大;
静态库升级后,程序必要重新编译链接
2) 动态库是在程序运行被载入代码中。
长处:程序在执行时加载动态库,代码体积小;程序升级更简朴;
不同应用程序如果调用相同的库,那么在内存里只必要有一份该共享库的实例。的地方肥瘦
缺点:运行时还必要动态库的存在,移植性较差
3.怎么创建进程
利用 fork() 函数来创建一个新的进程。fork() 函数会在当前进程的地点空间中创建一个新的进程,该新进程是当前进程的副本。新进程从 fork() 调用处开始执行,但它会拥有独立的进程 ID (PID)。
#include <iostream>
#include <unistd.h> // 包含 fork 函数的头文
int main() {
pid_t pid = fork(); // 调用 fork() 函数创建新进程
if (pid == 0) {
// 这里是子进程的代码
std::cout << "Hello from child process! PID: " << getpid() << std::endl;
} else if (pid > 0) {
// 这里是父进程的代码
std::cout << "Hello from parent process! Child PID: " << pid << std::endl;
} else {
// fork() 失败,无法创建新进程
std::cerr << "Failed to create child process!" << std::endl;
}
return 0;
}
4.什么是保卫进程
特点:保卫进程是后台进程;生命周期比较长,从系统启动时开启,系统关闭时结束;它是离开控制终端且周期执行的进程。
1) 创建子进程,父进程退出
2) 在子进程中创建新会话
3) 改变进程运行路径为根目录
4) 重设文件权限掩码
5) 关闭其他不必要的文件描述符
5.什么是僵尸进程?什么是孤儿进程?
若子进程先结束,父进程如果没有实时接纳,子进程变成僵尸进程(要避免僵尸进程产生)。
解决方法:
- 利用wait()或waitpid()系统调用:父进程应该在子进程结束后实时调用wait()或waitpid()系统调用往返收子进程的资源。这样可以确保子进程的进程描述符被实时释放,从而避免僵尸进程的产生。
- 设置SIGCHLD信号的处理函数:父进程可以设置一个SIGCHLD信号的处理函数,当子进程结束时,该信号会被发送到父进程。在信号处理函数中,父进程可以调用wait()或waitpid()往返收子进程的资源。
- 忽略SIGCHLD信号:如果父进程不关心子进程的退出状态,可以选择忽略SIGCHLD信号。这样,当子进程结束时,内核会自动接纳子进程的资源,不会产生僵尸进程。但必要注意的是,这种方法会使得父进程无法获取子进程的退出状态。
若父进程先结束,子进程成为孤儿进程,被init进程收养,会让子进程变成后台进程。
6.时间片相识么?
时间片是操作系统中用于调度进程的基本单位。在多道程序设计和多使命处理中,操作系统将 CPU 的执行时间分别成一小段小的时间片,每个进程在一个时间片内运行,然后切换到下一个进程。
时间片轮转算法是一种常见的调度算法,它将每个进程分配一个时间片,其时间片用完后,操作系统会暂停当前进程的执行,并将 CPU 分配给下一个就绪的进程,然后继承执行下一个时间片。这样,所有进程会依次获得 CPU 的执行机会,从用户的角度看,它们好像是同时运行的。
时间片的巨细通常由操作系统调度器决定,可以根据系统的性能、负载和战略来调解。如果时间片太小,会导致频仍的进程切换,增长系统开销;如果时间片太大,大概会导致长时间运行的进程占用 CPU 时间过长,导致其他进程响应变慢。
共性
动态性:进程和线程都是动态的概念,它们的存在和消亡都是动态的,具有一定的生命周期。
并发性:进程和线程都可以并发执行,即多个进程或多个线程可以同时存在于内存中,并在操作系统的调度下交替执行。
独立性:进程和线程在各自的执行空间内是相对独立的,它们拥有各自的数据结构和堆栈空间,互不干扰。
资源分配:无论是进程还是线程,操作系统都会为它们分配必要的资源,如内存、文件、I/O设备等。
区别
资源开销:进程是资源分配的基本单位,它拥有独立的内存空间和系统资源,因此创建和烧毁进程的开销相对较大。而线程是处理器调度的基本单位,它共享进程的资源,因此创建和烧毁线程的开销较小。
执行过程:进程是独立执行的,它拥有一个完整的执行情况。而线程是在进程内部执行的,多个线程共享进程的内存空间和资源。
通信机制:进程间通信(IPC)必要操作系统提供特别的机制,如管道、消息队列、共享内存等。而线程间通信则相对简朴,因为它们共享进程的内存空间,可以直接读写共享变量或利用简朴的同步机制。
稳定性:进程是操作系统分配资源的基本单位,因此进程瓦解通常不会影响到其他进程。而线程是进程的一部分,一个线程的瓦解大概导致整个进程的瓦解。
8.线程的同步 怎么实现
同步:在互斥的基础上按约定好的次序对临界资源举行操作
实现同步的机制:信号量、互斥锁+条件变量
include <stdio.h>
#include <pthread.h>
pthread_mutex_t mtx; // 互斥锁
pthread_cond_t cond; // 条件变量
int sharedResource = 0; // 共享资源
void* producer(void* arg) {
for (int i = 0; i < 5; i++) {
pthread_mutex_lock(&mtx);
sharedResource = i;/
printf("  roducer: Produced %d\n", i);
pthread_cond_signal(&cond); // 发送信号通知消费者
pthread_mutex_unlock(&mtx);
}
return NULL;
}
void* consumer(void* arg) {
for (int i = 0; i < 5; i++) {
pthread_mutex_lock(&mtx);
while (sharedResource < i) {
// 等待条件满足
pthread_cond_wait(&cond, &mtx);
}
printf("Consumer: Consumed %d\n", sharedResource);
pthread_mutex_unlock(&mtx);
}
return NULL;
}
int main() {
pthread_mutex_init(&mtx, NULL);
pthread_cond_init(&cond, NULL);
pthread_t producerThread, consumerThread;
pthread_create(&producerThread, NULL, producer, NULL);
pthread_create(&consumerThread, NULL, consumer, NULL);
pthread_join(producerThread, NULL);
pthread_join(consumerThread, NULL);
pthread_mutex_destroy(&mtx);
pthread_cond_destroy(&cond);
return 0;
}
9.线程的互斥怎么实现
互斥:同一时间只有一个线程对临界资源举行操作
实现互斥的机制:互斥锁
#include <stdio.h>
#include <pthread.h>
pthread_mutex_t mtx; // 定义互斥锁
void* printNumber(void* arg) {
int num = *(int*)arg;
pthread_mutex_lock(&mtx); // 加锁,制止其他线程访问共享资源
printf("%d\n", num);
pthread_mutex_unlock(&mtx); // 解锁,答应其他线程访问共享资源
return NULL;
}
int main() {
pthread_mutex_init(&mtx, NULL); // 初始化互斥锁
pthread_t t1, t2;
int num1 = 1, num2 = 2;
pthread_create(&t1, NULL, printNumber, (void*)&num1);
pthread_create(&t2, NULL, printNumber, (void*)&num2);
pthread_join(t1, NULL);
pthread_join(t2, NULL);
pthread_mutex_destroy(&mtx); // 烧毁互斥锁
return 0;
}
10.进程间通信方式有哪些?哪种服从最高
无名管道、有名管道、信号量、共享内存、信号灯集、消息队列、套接字
服从最高是共享内存:
共享内存服从最高的重要缘故原由是它避免了数据的复制和传输。在共享内存中,多个进程可以直接访问同一块物理内存,无需举行数据的拷贝和传输,因此在数据量较大的情况下,共享内存的服从要远高于其他进程间通信方式。
具体来说,以下是共享内存服从高的几个关键点:
避免数据拷贝:在其他进程间通信方式(如管道、消息队列等)中,数据必要从一个进程的地点空间复制到内核缓冲区,然后再从内核缓冲区复制到另一个进程的地点空间,涉及两次数据拷贝操作。而在共享内存中,多个进程共享同一块物理内存,不必要举行数据拷贝,直接读写共享内存即可。
高效的数据访问:共享内存的数据直接位于物理内存中,而其他进程间通信方式的数据位于内核缓冲区,因此在共享内存中访问数据更加高效。
无需内核介入:在共享内存中,数据的读写不必要内核的介入,减少了系统调用和上下文切换,提高了通信的速度和服从。
11.进程间通信方式的优缺点对比
共享内存适适用于大量数据的高效传输、
管道和消息队列适用于进程间的一对一通信、
套接字适合于网络通信
12.有名管道和无名管道的区别?
无名管道
具有亲缘关系的进程间
半双工通信方式,有固定的读端和写端,通过文件描述符操作
管道中没有数据时,读阻塞
管道中写满数据时,写阻塞
pipe(int fd[2])
文件IO中的read/write
有名管道
互不相关的两个进程间
在路径中存在管道文件,遵循先辈先出,不支持lseek
只读方式打开,读阻塞
只写方式打开,写阻塞
mkfifo(“fifo”,0666);
文件IO的open/read/write/close
| 无名管道
| 有名管道
| 利用场景
| 具有亲缘关系的进程间
| 不相干的两个进程可以利用
| 特点
| 固定的读端fd[0]和写端fd[1]
可以看作一种特别的文件
通过文件IO操作
| 在文件系统中存在管道文件,但是数据读写在内核空间中
通过文件IO举行操作
不支持lseek操作,先辈先出
| 函数
| pipe()
直接read\write
| mkfifo()
先打开open(),再读写read\write
| 读写特性
| 当管道中无数据时读阻塞
当管道写满时写阻塞
当关闭读端向管道中写会管道破裂
| 只写方式打开阻塞直到另一个进程把读打开
只读方式打开阻塞直到另一个进程把写打开
可读可写打开,如果无数据读阻塞
|
13.共享内存的实现方式
创建共享内存:
首先,必要创建一块共享内存区域。在 Linux 系统中,可以利用 shmget 系统调用来创建或获取共享内存。必要提供一个唯一的键值来标识共享内存区域,并可以指定一些标记和权限来控制内存区域的属性。
映射共享内存:
一旦共享内存区域被创建,进程可以利用 sh mat 系统调用将共享内存区域关联到自己的地点空间中。必要提供共享内存的标识符,如果有多块共享内存区域,可以通过指定不同的标识符来关联不同的区域。关联后,进程就可以直接访问共享内存中的数据。
利用共享内存:
一旦共享内存区域被关联到进程的地点空间中,进程可以像访问普通内存一样直接读写共享内存中的数据。多个进程可以共享同一块物理内存,无需举行数据的拷贝和传输,提高了通信的服从。
排除关联:
当不再必要共享内存时,进程可以利用 shmdt 系统调用将共享内存区域从自己的地点空间中排除关联。排除关联后,进程将无法再访问共享内存中的数据。
删除共享内存:
当所有进程都排除了对共享内存的关联,可以利用 shmctl 系统调用删除共享内存区域,释放相关资源。必要注意,删除共享内存只是将共享内存标记为删除状态,现实的内存接纳会在所有进程都排除关联后举行。
14.消息队列的实现方式
(1)创建key值ftok
创建消息队列:
必要创建一个唯一的值key键来标识该消息队列,并可以指定一些标记来控制队列的属性。
利用系统调用(如 msgget)来创建一个消息队列。如果消息队列已经存在,可以通过指定相同的键值获取已有的消息队列。
发送消息到队列:
利用系统调用(如 msgsnd)将消息发送到队列中。必要指定消息队列的标识符、要发送的消息内容、消息的巨细和一些标记。发送的消息必要封装成特定格式,包罗消息类型和现实数据。
接收消息:
其他进程可以利用系统调用(如 msgrcv)从消息队列中接收消息。必要指定消息队列的标识符、用于接收消息的缓冲区、缓冲区的巨细、要接收的消息类型和一些标记。如果队列中没有符合条件的消息,选择阻塞等
接收进程可以
或立即返回。
删除消息队列:
当不再必要消息队列时,可以利用系统调用(如 msgctl)将其删除,释放相关资源。删除消息队列前,必要确保所有进程都已经停止利用该队列。
15.fork和vfork区别
fork 和 vfork 是两种在 Linux/Unix系统中用于创建新进程的系统调用,它们有一些区别:
fork:
fork 是创建新进程的标准方法,它会复制当前进程的所有资源(包罗代码、数据、堆栈等),创建一个与父进程几乎完全相同的子进程。
父进程和子进程之间的地点空间是独立的,互相不会影响。子进程从 fork 调用之后的位置开始执行,可以通过返回值来判定当前进程是父进程还是子进程。
在 fork 调用后,父进程和子进程并发执行,并共享一些资源,比如打开的文件描述符、信号处理器等。
父进程和子进程的执行次序是不确定的,取决于系统调度器的调度战略。
vfork:
vfork 也是用于创建新进程的系统调用,但它与 fork 有一些不同之处。
vfork 创建的子进程与父进程共享地点空间,即子进程与父进程共用同一份数据和代码。这意味着在子进程中执行的任何修改都会直接影响到父进程,因此 vfork 的利用要非常小心。
vfork 是为了在子进程中立即执行一个新程序(通常是通过 exec 系统调用),然后立即退出,不必要复制父进程的地点空间,以节省资源。
在 vfork 调用后,父进程会被阻塞,直到子进程执行完毕或调用 exec 系统调用后才会继承执行。
总的来说,fork 是创建新进程的常规方法,而 vfork 适用于在子进程中立即执行一个新程序。在利用 vfork 时必要格外小心,避免对父进程的地点空间造成破坏。通常情况推荐利用 fork 来创建新进程。
16.线程的死锁,怎么避免?
死锁:
是指两个或两个以上的线程在执行过程中,由于竞争资源或者由于彼此通信而造成 的一种阻塞的现象,若无外力作用,它们都将无法推进下去。
死锁产生的四个必要条件:
1、互斥利用,即当资源被一个线程利用(占有)时,别的线程不能利用
- 不可抢占,资源请求者不能欺压从资源占有者手中夺取资源,资源只能由资源占有者主动释放
3、请求和保持,即当资源请求者在请求其他的资源的同时保持对原有资源的占有。
4、循环等待,即存在一个等待队列:P1占有P2的资源,P2占有P3的资源,P3占有P1的资源。这样就形成了一个等待环路。
注意:当上述四个条件都成立的时候,便形成死锁。固然,死锁的情况下如果打破上述任何一个条件,便可让死锁消散。
解决方法
(1)避免循环等待:确保线程获取资源的次序是一致的,避免形成循环等待的情况
(2)利用资源分级:将资源分为不同的等级或优先级,确保线程按照一定的次序获取资源
(3)利用超机会制:在获取资源时,设置一个超时时间,并在超过时间限定后放弃获取资源并释放已持有的资源
(4)避免资源的重复占用:只管避免在一个线程中重复获取已经持有的资源
(5)公道规划资源的利用
(6)利用死锁检测和恢复机制
二、网络编程:
1. TCP与UDP的异同点
1.共同点:
同为传输层协议
TCP:有毗连,可靠:无误、数据无丢失、数据无失序、数据无重复到达
UDP:无毗连,不保证可靠
3.应用场所:
TCP:传输质量较高,如qq登陆操作
UDP:对传输质量要求不高,但要保证服从,如qq聊天、语聊、视频。广播和组播
2. TCP的三次握手过程
三次握手过程:
第一次握手:建立毗连时,客户端发送syn包(seq=j)到服务器,并进入SYN_SENT状态,等待服务器确认;SYN:同步序列编号(Synchronize Sequence Numbers)。
第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(seq=k),即SYN+ACK包,此时服务器进入SYN_RECV状态。
第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED(TCP毗连乐成)状态,完成三次握手。
3. TCP的四次挥手过程
四次挥手过程:
第一次挥手:某个应用进程首先调用close,我们称这一端执行主动关闭。于是这一端的TCP发送一个FIN分节,表现数据发送完毕。
第二次挥手:接收到FIN的另一端执行被动关闭(passive close)。这个FIN由TCP确认。它的接收也作为文件结束符传递给接收端应用进程(放在已排队期待应用进程接收到任何其他数据之后)
第三次挥手:一段时间后,接收到文件结束符的应用进程将调用close关闭它的套接口。这导致它的TCP也发送一个FIN。
第四次挥手:接收到这个FIN的原发送端TCP对它举行确认。
面向字节的数据传送流(如TCP字节流、Unix管道等)也利用EOF表现在某个方向上不再有数据待传送。在TCP字节流中,EOF的读或写通过收发一个特别的FIN分节来实现
4. TCP是怎样保证可靠传输的
校验:TCP 将保持它首部和数据的检验和。这是一个端到端的检验和,目的是检测数据在传输过程中的任何变化。如果收到端的检验和有差错,TCP 将抛弃这个报文段和不确认收到此报文段。
序列号:TCP 传输时将每个字节的数据都举行了编号,这就是序列号。(为了应对延时抵达和排序混乱)。每个毗连都会选择一个初始序列号,初始序列号(视为一个 32 位计数器),会随时间而改变(每 4 微秒加 1)。因此,每一个毗连都拥有不同的序列号。序列号的作用不仅仅是应]答的作用,有了序列号能够将接收到的数据根据序列号排序,而且去掉重复序列号的数据。这也是 TCP 传输可靠性的保证之一。
确认应答:TCP 传输的过程中,每次接收方收到数据后,都会对传输方举行确认应答。也就是发送 ACK 报文。这个 ACK 报文当中带有对应的确认序列号,告诉发送方,接收到了哪些数据,下一次的数据从哪里发。
超时重传:超时重传机制。简朴理解就是发送方在发送完数据后等待一个时间,时间到达没有接收到 ACK 报文,那么对刚才发送的数据举行重新发送。如果是刚才第一个缘故原由,接收方收到二次重发的数据后,便举行 ACK 应答。如果是第二个缘故原由,接收方发现接收的数据已存在(判定存在的根据就是序列号,所以上面说序列号还有去除重复数据的作用),那么直接抛弃,仍旧发送 ACK 应答。那么发送方发送完毕后等待的时间i是多少呢?如果这个等待的时间过长,那么会影响 TCP 传输的团体服从,如果等待时间过短,又会导致频仍的发送重复的包。怎样权衡?由于 TCP 传输时保证能够在任何情况下都有一个高性能的通信,因此这个最大超时时间(也就是等待的时间)是动态计算的。
毗连管理:说白了就是三次握手四次挥手。
流量控制:当接收方来不及处剃头送方的数据,能提示发送方降低发送的速率,防止包丢失。
拥塞控制:拥塞控制是 TCP 在传输时尽大概快的将数据传输,而且避免拥塞造成的一系列题目。是可靠性的保证,同时也是维护了传输的高效性。
5. 怎样实现并发服务器
多线程并发服务器:
利用一个主线程监听服务器端口,当有客户端毗连请求时,主线程继承毗连并创建一个新的线程来处理该毗连。
每个线程负责与一个客户端举行通信,接收客户端发送的数据并举行相应的处理,然后将处理结果发送给客户端。
多个线程之间共享服务器资源,如共享的数据结构、文件描述符等。必要利用互斥锁等同步机制来保证线程间的数据安全。
多进程并发服务器:
利用一个主进程监听服务器端口,当有客户端毗连请求时,主进程继承毗连并创建一个新的子进程来处理该毗连。
每个子进程负责与指定一个客户端举行通信,接收客户端发送的数据并举行相应的处理,然后将处理结果发送给客户端。
子进程之间独立运行,拥有各自的地点空间,不会相互影响。
多个进程之间不共享资源,必要利用进程间通信(IPC)机制来传递数据,如管道、消息队列、共享内存等。
多进程:
长处: 服务器更稳定 , 父子进程资源独立, 安全性高一点
缺点: 必要开辟多个进程,大量消耗资源
多线程:
长处: 相对多进程, 资源开销小, 线程共享同一个进程的资源
缺点: 必要开辟多个线程,而且线程安全性较差
IO多路复用:
长处: 节省资源, 减小系统开销,性能高;
缺点: 代码复杂性高
6. select、poll、epoll的区别
select:
1. 一个进程最多只能监听1024个文件描述符 (千级别)
- select被唤醒之后必要重新轮询一遍,服从比较低(消耗CPU资源);
3. select每次会清空表,每次都必要拷贝用户空间的表到内核空间,服从低(一个举行0~4G,0~3G是用户态,3G~4G是内核态,拷贝是非常耗时的);
poll:
1. 优化文件描述符个数的限定;(根据poll函数第一个函数的参数来定,如果监听的变乱为1个,则结构体数组的巨细为1,如果想监听100个,那么这个结构体数组的巨细就为100,由程序员自己来决定)
2. poll被唤醒之后必要重新轮询一遍驱动的poll函数,服从比较低
3. poll不必要重新构造文件描述符表,只必要从用户空间向内核空间拷贝一次数据即可
epoll:(本世纪最好用的io多路复用机制)
1. 监听的最大的文件描述符没有个数限定(理论上,取决与你自己的系统)
2. epoll当有变乱产生被唤醒之后,文件描述符主动调用callback函数直接拿到唤醒的文件描述符,将文件描述符拷贝到用户空间即可
- epoll不必要重新构造文件描述符表,只必要从用户空间向内核空间拷贝一次数据即可
| select
| poll
| epoll
| 监听个数
| 一个进程最多监听1024个文件描述符
| 由程序员自己决定
| 百万级
| 方式
| 每次都会被唤醒,都必要重新轮询
| 每次都会被唤醒,都必要重新轮询
| 红黑树内callback自动回调,不必要轮询
| 服从
| 文件描述符数量越多,轮询越多,服从越低
| 文件描述符数量越多,轮询越多,服从越低
| 不轮询,服从高
| 原理
| 每次利用select后,都会清空表
每次调用select,都必要拷贝用户空间的表到内核空间
内核空间负责轮询监督表内的文件描述符,将发生变乱的文件描述符拷贝到用户空间,再次调用select,如此循环
| 不会清空结构体数组
每次调用poll,都必要拷贝用户空间的结构体到内核空间
内核空间负责轮询监督结构体数组内的文件描述符,将发生变乱的文件描述符拷贝到用户空间,再次调用poll,如此循环
| 不会清空表
epoll中每个fd只会从用户空间到内核空间只拷贝一次(epoll_ctl添加ADD时)
通过epoll_ctl将文件描述符交给内核羁系,一旦fd就绪,内核就会采用callback的回调机制来激该死fd,epoll_wait便可以收到通知(内核空间到用户空间的拷贝
| 特点
|
- 一个进程最多能监听1024个文件描述符
- select每次被唤醒,都要重新轮询表,服从低
- select每次都清空未发生相应的文件描述符,每次都要拷贝用户空间的表到内核空间
|
- 优化文件描述符的个数限定
- poll每次被唤醒,都要重新轮询,服从比较低(耗费cpu)
- poll不必要构造文件描述符表(也不必要清空表),采用结构体数组,每次也必要从用户空间拷贝到内核空间
|
- 监听的文件描述符没有个数限定(取决于自己的系统)
- 异步IO,epoll当有变乱产生被唤醒,文件描述符会主动调用callback函数拿到唤醒的文件描述符,不必要轮询,服从高
- epoll不必要构造文件描述符的表,只必要从用户空间拷贝到内核空间一次。
| 结构
| 文件描述符表(位表)
| 结构体数组
| 红黑树和就绪链表
| 开辟复杂度
| 低
| 低
| 中
|
7. Tcp的粘包题目
TCP的粘包题目是指在传输过程中,由于TCP协议的特性,多个数据包大概会被合并成一个大的数据包,或者一个数据包被拆分成多个小的数据包,从而导致接收端无法精确解析和处理数据。
造成TCP粘包题目的重要缘故原由是TCP协议是面向流的,数据流在发送端和接收端之间是接二连三的,而没有消息边界的概念。因此,多个数据包在传输过程中大概会被合并成一个大的数据流,或者一个数据包被拆分成多个小的数据流。
解决TCP粘包题目的常见方法有以下几种:
固定长度消息:
发送端将每个数据包固定长度发送,接收端按照固定长度来接收息争析数据。这种方法简朴直接,但大概会造成数据浪费,因为某些数据包大概会很大,而其他数据包大概会很小。
消息边界标记:
发送端在每个数据包的末尾添加特定的标记来表现消息的结束,接收端通过检测标记来辨认消息的边界。例如,可以在每个数据包的末尾添加换行符或其他特定字符作为消息边界。
消息长度字段:
发送端在每个数据包的头部添加一个表现消息长度的字段,接收端先读取消息长度字段,然后根据消息长度来接收息争析数据。这种方法比固定长度消息更灵活,但必要处理消息长度字段大概被拆分的情况。
利用专门的消息协议:
可以定义自己的消息协议,在消息中包含消息长度字段、消息类型等信息,使得接收端可以精确解析和处理数据。
应用层处理:
在应用层举行数据的拼接息争析,将多个小数据包合并成一个完整的消息。
8. UDP的丢包题目
UDP的丢包题目是指在UDP协议传输过程中,由于网络缘故原由或接收端处理能力不足,部分数据包大概在传输过程中丢失,导致接收端无法收到完整的数据。
UDP是一种无毗连、不可靠的传输协议,它不提供可靠性保证,不保证数据包的次序和可靠传输。因此,UDP的丢包题目是很常见的情况,特别是在网络状况较差或网络拥堵的情况下更轻易发生。
造成UDP丢包题目的重要缘故原由包罗:
- 网络拥堵:当网络中的数据流量超过网络设备处理能力时,会导致数据包丢失。
- 网络延迟:网络传输的延迟会导致数据包到达接收端的时间不确定,从而大概造成数据包的丢失。
- 缓冲区溢出:接收端的缓冲区巨细有限,如果数据到达速度过快,缓冲区大概会溢出,导致部分数据包丢失。
- 数据包巨细:UDP本身没有数据包巨细限定,但在网络传输中,数据包过大大概会)被分片,而分片大概会造成部分数据包丢失。
要解决UDP的丢包题目,可以考虑以下方法:
- 重传机制:在应用层实现重传机制,发送端定时重发未确认的数据包,确保接收端收到完整的数据。
- 数据包校验:可以在应用层添加数据包序号和校验码等信息,接收端通过校验和来查抄数据的完整性,抛弃校验和错误的数据包。
- 网络优化:优化网络拓扑和带宽,减少网络延迟和拥堵,提高数据传输的稳定性。
- 应用层处理:在应用层对数据举行分段、拼接和校验,确保数据的完整性。
9. TCP编程框架
服务器端:
socket()函数创建流式套接字用于建立毗连
bind()函数绑定服务器ip和端口号
listen()函数改变套接字属性化主动为被动
accept()函数等待毗连产生用于通信的套接字
send()/recv()函数读写
close()关闭文件描述符
客户端:
socket()函数创建流式套接字用于通信
connect()函数建立与服务器的毗连
send()/recv()函数读写
close函数关闭文件描述符
Wireshark
Wireshark过滤规则及利用方法-CSDN博客
tcpdump
https://www.cnblogs.com/jiujuan/p/9017495.html
12. 广播和组播的区别
一、主体不同*
- 组播:为了减少在广播中涉及的不必要的开销,可以只向特定的一部分接收方(可以是域内也可以是域间)发送流量。
2、广播:将报文发送到网络中的所有大概的接收者。
二、原理不同
- 组播:在通信中参与或感兴趣的主机必要处理相关的分组,流量只会 被承载于它将被利用的链路上,而且只有恣意组播数据报的一个副本被承载于这样的链路上。
2、广播:路由器简朴地将它接收到的任何广播报文副本转发到除该报文到达的接口以外的每个接口。
三、特点不同
1、组播:通过发送方指明接收方,或是通过接收方独立地指明就可以完。成这项工作。然后网络只负责向预期的或感兴趣的收件方发送流量。
2、广播:通过将地点中的主机部分全部置1形成的,特别地点255.255.255.255对应于当地网络广播。
12. Tcp/Ip网络模型分为几层?每一层什么作用?都有哪些协议?
TCP/IP网络模型分为四层,每一层的作用和常见协议如下:
应用层(Application Layer):
应用协议和应用程序的聚集
常见协议:HTTP、FTP、SMTP、DNS、Telnet、SSH、SNMP等。
传输层(Transport Layer):
端到端,决定数据交给机器的哪个使命(进程)去处理,通过端口寻址。
常见协议:TCP(传输控制协议)、UDP(用户数据报协议)。
网络层(Internet Layer):
提供设备对设备的传输,可以理解为通过IP寻址机器。
常见协议:IP、ICMP、IGMP。
网络接口和物理层(Network interfaces and physical layers):
屏蔽硬件差异(驱动),向上层提供统一的操作接口。
常见协议:Ethernet、(Point-to-Point Protocol)、ARP(Address Resolution Protocol)、RARP(Reverse Address Resolution Protocol)。
13. OSI模型?
物理层(Physical Layer):
物理层负责传输比特流,重要定义物理介质和电气特性,以及数据传输的硬件细节。
数据链路层(Data Link Layer):
数据链路层负责将数据包分别成帧,并处理帧的传输和接收。
传输层(Transport Layer):
传输层提供端到端的数据传输服务,确保数据的可靠传输和错误恢复。
提供端口号、流量控制和数据重传等功能,常见的传输层协议有TCP和UDP。
会话层(Session Layer):
会话层负责建立、管理和停止会话(通信毗连)。
管理不同设备之间的对话,确保数据传输的次序和同步。
表现层(Presentation Layer):
表现层负责数据的格式化和转换,确保数据在不同系统中的表现息争释相互兼容。
对数据举行加密、压缩、编码息争码等处理。
应用层(Application Layer):
应用层提供网络应用程序和用户之间的接口,负责应用程序的通信。
各种网络应用,如电子邮件、文件传输、远程登录等都在应用层实现。
14. 学过什么数据库?增删改查语句?
MySQL和SQLite
大型数据库 :Oracle
中型数据库 :Server是微软开辟的数据库产品,重要支持windows平台
小型数据库 : mySQL是一个小型关系型数据库管理系统。开放源码 (嵌入式不必要存储太多数据)
SQL基础语句基本利用
15. MySQL和SQLite区别
嵌入式数据库:
MySQL是典型的客户端-服务器架构数据库,必要通过网络毗连来访问数据库。它支持多用户、多线程的并发操作,适用于大型应用和高并发场景。
SQLite是一种嵌入式数据库,直接嵌入到应用程序中,不必要独立的服务器进程。它适用于轻量级应用和单用户情况。
数据库巨细和性能:
MySQL适用于大型数据库和高性能需求,支持复杂的查询和大规模的数据存储。
SQLite适用于小型数据库和低资源情况,它的存储引擎简朴高效,适合移动设备和嵌入式系统。
数据库特性:
MySQL持支完整的SQL语法,包罗事务处理、视图、存储过程、触发器等高级特性。
SQLite支持大部分SQL语法,但不支持存储过程和触发器等高级特性。
摆设和管理:
MySQL必要单独摆设和配置数据库服务器,必要额外的管理和维护工作。
SQLite作为嵌入式数据库,不必要独立的服务器,摆设和管理比较简朴。
存储引擎:
MySQL支持多种存储引擎,如InnoDB、M0yISAM等,可以根据需求选择不同的存储引擎。
SQLite只有一个存储引擎,但它在大部分场景下性能较好。
- 网络编程中做的项目,在简历中写的重点会问到
- 四种IO
- 阻塞IO:最常见、服从低、不浪费cpu
- 非阻塞式IO:轮询、耗费CPU、可以处理多路IO
- 信号驱动IO/异步IO:异步通知方式,必要底层驱动的支持
- IO多路复用:可以同时处理多路IO,不必要轮询,服从高
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |