本文共 2219 字,大约阅读时间需要 7 分钟。
如果服务器不仅仅要响应客户端的连接请求,还要处理其他事件,就可以考虑基于IO多路复用的并发编程。
IO多路复用就是对多个独立的IO事件做一个统一的管理,比如服务器既要响应客户端的连接请求,同时还要接收从键盘输入的数据,就可以将监听socket和标准输入stdin加入select函数进行管理。
比较常用的IO多路复用接口有:select、poll、epoll
关于select,要注意的有:
典型的基于select的IO多路复用并发编程:
IO多路复用的优势劣势:
在多进程中,每个逻辑流都使用了单独的进程,具有独立的地址空间,开销大,而且流之间共享数据麻烦。
在IO多路复用中,每个逻辑流都是运行在一个进程中,共享进程数据地址空间,流之间共享数据容易。
基于多线程的并发编程相当于两种方法的混合:线程也是运行在进程上下文中的逻辑流,线程共享进程的地址空间,但是相比于IO多路复用的共享所有数据,线程之间还是有独立的线程上下文的,比如:线程ID、栈、栈指针、程序计数器、通用目的寄存器和条件码,和进程一样,线程由内核自动调度,并且内核通过一个整数ID来识别线程。
线程有自己独立的上下文,同时也可以访问进程的地址空间,创建出的线程和原来的主线程是对等关系,而且执行的时候是流式的,也就是进程中同一时刻只能有一个线程在执行,所以就需要有专门的函数来使主线程阻塞,给其他线程执行的机会,比如pthread_join()
函数:
而且在被其他线程回收之前,线程的资源的不会释放的!!!当然,可以通过分离线程来实现线程结束自动释放,但是当分离线程之后,主线程就和线程断开连接了,无法了解线程的状态。
线程的执行模型如下:
一组并发线程运行在一个进程的上下文中。每个线程都有它自己 独立的 线程上 下文,包括线程 ID、 栈、 栈指针、程序计数器、条件码和通用目的寄存器值。每个线程和其他线程一起共享进程上下文的剩余部分。这包括整个用户虚拟地址空间,它是由只读文本(代码)、 读/写数据、堆以及所有的共享库代码和数据区域组成的。 线程也共享相同的打开文件的集合。
从实际操作的角度来说, 让一个线程去读或写另一个线程的寄存器值是不可能的。另一方面,任何线程都可以访问共享虚拟内存的任意位置。如果某个线程修改了一个内存位置,那么其他每个线程最终都能在它读这个位置时发现这个变化。因此,寄存器是从不共享的,而虚拟内存总是共享的。多线程中经常使用信号量来同步。
题目:
局域网内有一主机ip为192.168.1.2,请找到他的mac地址?
答案:先ping 192.168.1.2
然后使用指令arp -a
查看ARP缓存表,在表中查看IP地址对应的MAC地址
采用递归实现:
#includevoid fun(char *p);int main(){ char str[1000]; scanf("%s", str); getchar(); fun(str); printf("\n"); return 0;}void fun(char *p){ if (*p != '\0') { //循环结束 //fun(++p); 不可以++p,不然下面打印出的就是++p之后的了 fun(p + 1); } printf("%c", *p); return ;}
关于virtual void Draw()=0,下面说法正确的有几个?
(1)它是纯虚函数
(2)它在定义它的类中不能实现
(3)定义它的类不可实例化
(4)如果一个类要继承一个ADT类,必须要实现其中的所有纯虚函数
正确:1、2、3
虚函数与纯虚函数:https://blog.csdn.net/u012260238/article/details/53610462