每日一练(二十七)

1.6 基于IO多路复用的并发编程

如果服务器不仅仅要响应客户端的连接请求,还要处理其他事件,就可以考虑基于IO多路复用的并发编程。

IO多路复用就是对多个独立的IO事件做一个统一的管理,比如服务器既要响应客户端的连接请求,同时还要接收从键盘输入的数据,就可以将监听socket和标准输入stdin加入select函数进行管理。

比较常用的IO多路复用接口有:select、poll、epoll

image-20201230102921953

关于select,要注意的有:

  • 使用select系统调用会挂起进程,直至有一个或多个IO事件发生,才会将控制权交给进程
  • select每次调用都要更新集合,因为select会将可读事件也从集合中返回

典型的基于select的IO多路复用并发编程:
在这里插入图片描述

IO多路复用的优势劣势:

  • 优势:基于IO多路复用的服务器是运行在单一进程的上下文中的,所以每个逻辑流都能够访问进程的全部地址空间,这使得在数据流之间共享数据变得容易。方便使用调试工具对并发服务器进行调试。
  • 劣势:使得程序变得复杂,编码更加复杂。

1.7 基于多线程的并发编程

在多进程中,每个逻辑流都使用了单独的进程,具有独立的地址空间,开销大,而且流之间共享数据麻烦。

在IO多路复用中,每个逻辑流都是运行在一个进程中,共享进程数据地址空间,流之间共享数据容易。

基于多线程的并发编程相当于两种方法的混合:线程也是运行在进程上下文中的逻辑流,线程共享进程的地址空间,但是相比于IO多路复用的共享所有数据,线程之间还是有独立的线程上下文的,比如:线程ID、栈、栈指针、程序计数器、通用目的寄存器和条件码,和进程一样,线程由内核自动调度,并且内核通过一个整数ID来识别线程。

线程有自己独立的上下文,同时也可以访问进程的地址空间,创建出的线程和原来的主线程是对等关系,而且执行的时候是流式的,也就是进程中同一时刻只能有一个线程在执行,所以就需要有专门的函数来使主线程阻塞,给其他线程执行的机会,比如pthread_join()函数:
在这里插入图片描述

而且在被其他线程回收之前,线程的资源的不会释放的!!!当然,可以通过分离线程来实现线程结束自动释放,但是当分离线程之后,主线程就和线程断开连接了,无法了解线程的状态。

线程的执行模型如下:
image-20210125141516575

一组并发线程运行在一个进程的上下文中。每个线程都有它自己 独立的 线程上 下文,包括线程 ID、 栈、 栈指针、程序计数器、条件码和通用目的寄存器值。每个线程和其他线程一起共享进程上下文的剩余部分。这包括整个用户虚拟地址空间,它是由只读文本(代码)、 读/写数据、堆以及所有的共享库代码和数据区域组成的。 线程也共享相同的打开文件的集合。
从实际操作的角度来说, 让一个线程去读或写另一个线程的寄存器值是不可能的。另一方面,任何线程都可以访问共享虚拟内存的任意位置。如果某个线程修改了一个内存位置,那么其他每个线程最终都能在它读这个位置时发现这个变化。因此,寄存器是从不共享的,而虚拟内存总是共享的。

多线程中经常使用信号量来同步。

1.8 根据局域网内ip地址找到MAC地址

题目:

局域网内有一主机ip为192.168.1.2,请找到他的mac地址?

答案:先ping 192.168.1.2 然后使用指令arp -a查看ARP缓存表,在表中查看IP地址对应的MAC地址

1.9 反转输出字符串

采用递归实现:

#include <stdio.h>

void 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 ;
}

1.10 纯虚函数相关选择题

关于virtual void Draw()=0,下面说法正确的有几个?

(1)它是纯虚函数

(2)它在定义它的类中不能实现

(3)定义它的类不可实例化

(4)如果一个类要继承一个ADT类,必须要实现其中的所有纯虚函数

正确:1、2、3

  • 类里如果声明了虚函数,这个函数是实现的,哪怕是空实现,它的作用就是为了能让这个函数在它的子类里面可以被覆盖(override),这样的话,编译器就可以使用后期绑定来达到多态了。纯虚函数只是一个接口,是个函数的声明而已,它要留到子类里去实现。
  • 虚函数在子类里面可以不重写;但纯虚函数必须在子类实现才可以实例化子类。
  • 虚函数的类用于 “实作继承”,继承接口的同时也继承了父类的实现。纯虚函数关注的是接口的统一性,实现由子类完成。
  • 带纯虚函数的类叫抽象类,这种类不能直接生成对象,而只有被继承,并重写其虚函数后,才能使用。抽象类被继承后,子类可以继续是抽象类,也可以是普通类。
  • 虚基类是虚继承中的基类,具体见下文虚继承。

虚函数与纯虚函数:https://blog.csdn.net/u012260238/article/details/53610462

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值