面试题目整理

其中进程和线程的问题及链表的问题提问几率极高

1.利用socket抓取网页

  1. 获取网页ip(可以通过域名来获取网页的ip地址)
      website_host = gethostbyname(url.c_str());
  2. 建立socket
     sockfd = socket(AF_INET, SOCK_STREAM, 0);
  3. 初始化地址结构
    website_addr.sin_family = AF_INET;
    website_addr.sin_port = htons(80);
    website_addr.sin_addr.s_addr = ((struct in_addr *)(website_host->h_addr))->s_addr;
  4. socket建连
    ret = connect(sockfd, (struct sockaddr*)&website_addr, sizeof(website_addr));
  5. 向80端口发送http头
  6. 接收网页信息
    fd = open("recv.html", O_RDWR)

详情代码见:socket抓取网页 - phlsheji - 博客园https://www.cnblogs.com/bhlsheji/p/4660602.html

2.io多路复用:

  1. (1)同步阻塞IO(Blocking IO):即传统的IO模型。
    (2)同步非阻塞IO(Non-blocking IO):默认创建的socket都是阻塞的,非阻塞IO要求socket被设置为NONBLOCK。
    (3)IO多路复用(IO Multiplexing):即经典的Reactor设计模式,有时也称为异步阻塞IO,Java中的Selector和Linux中的epoll都是这种模型。
    (4)异步IO(Asynchronous IO):即经典的Proactor设计模式,也称为异步非阻塞IO。
  2. 同步和异步的概念描述的是用户线程与内核的交互方式:同步是指用户线程发起IO请求后需要等待或者轮询内核IO操作完成后才能继续执行;而异步是指用户线程发起IO请求后仍继续执行,当内核IO操作完成后会通知用户线程,或者调用用户线程注册的回调函数。
    阻塞和非阻塞的概念描述的是用户线程调用内核IO操作的方式:阻塞是指IO操作需要彻底完成后才返回到用户空间;而非阻塞是指IO操作被调用后立即返回给用户一个状态值,无需等到IO操作彻底完成。
  3. IO多路复用模型是建立在内核提供的多路分离函数select基础之上的,使用select函数可以避免同步非阻塞IO模型中轮询等待的问题。
    如图所示,用户首先将需要进行IO操作的socket添加到select中,然后阻塞等待select系统调用返回。当数据到达时,socket被激活,select函数返回。用户线程正式发起read请求,读取数据并继续执行。
    从流程上来看,使用select函数进行IO请求和同步阻塞模型没有太大的区别,甚至还多了添加监视socket,以及调用select函数的额外操作,效率更差。但是,使用select以后最大的优势是用户可以在一个线程内同时处理多个socket的IO请求。用户可以注册多个socket,然后不断地调用select读取被激活的socket,即可达到在同一个线程内同时处理多个IO请求的目的。而在同步阻塞模型中,必须通过多线程的方式才能达到这个目的

  4. 详情见:IO多路复用机制详解 - Yeang - 博客园
  5. select函数注意点见:多路复用之select_心.跳的博客-CSDN博客_多路分离函数select

3.哈希表的实现:

        数组+哈希函数+冲突处理

4.单链表反转:

        包括头指针共三个指针,依次读取一个节点就将其插入到头节点之后即可实现原地反转

5.C语言创建多进程/线程:

        进程: Linux下的多线程程序,需要使用头文件pthread.h,链接时需要使用库libpthread.a
                    线程的创建通过函数pthread_create来完成

        线程:fork可以用来创建一个进程,当我们在一个循环体中,就可以多次fork,创建多个进程

6.进程线程的区别和进程的通信方式:

        进程和线程的定义:进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进 程是系统进行资源分配和调度的一个独立单位.
        线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源.

        进程和线程的关系:一个线程可以创建和撤销另一个线程;同一个进程中的多个线程之间可以并发执行.     相对进程而言,线程是一个更加接近于执行体的概念,它可以与同进程中的其他线程共享数据,但拥有自己的栈空间,拥有独立的执行序列。

        进程和线程的区别: 进程和线程的主要差别在于它们是不同的操作系统资源管理方式。进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不同执行路径。线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉,所以多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。但对于一些要求同时进行并且又要共享某些变量的并发操作,只能用线程,不能用进程。简而言之,一个程序至少有一个进程,一个进程至少有一个线程.

        进程的通信方式: 

       1.匿名管道(pipe)通信:管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用。进程的亲缘关系通常是指父子进程关系               
父进程创建管道,得到两个⽂件描述符指向管道的两端
父进程fork出子进程,⼦进程也有两个⽂件描述符指向同⼀管道。
父进程关闭fd[0],子进程关闭fd[1],即⽗进程关闭管道读端,⼦进程关闭管道写端(因为管道只支持单向通信)。⽗进程可以往管道⾥写,⼦进程可以从管道⾥读,管道是⽤环形队列实现的,数据从写端流⼊从读端流出,这样就实现了进程间通信。
       2.高级管道(popen):将另一个程序当做一个新的进程在当前程序进程中启动,则它算是当前程序的子进程,这种方式我们成为高级管道方式。
       3.有名管道 (named pipe) : 有名管道也是半双工的通信方式,但是它允许无亲缘关系进程间的通信。
       4.消息队列( message queue ) : 消息队列是由消息的链表,存放在内核中并由消息队列标识符标识。消息队列克服了信号传递信息少、管道只能承载无格式字节流以及缓冲区大小受限等缺点。
       5.信号量( semophore ) : 信号量是一个计数器,可以用来控制多个进程对共享资源的访问。它常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。因此,主要作为进程间以及同一进程内不同线程之间的同步手段。
       6.信号 ( sinal ) : 信号是一种比较复杂的通信方式,用于通知接收进程某个事件已经发生。
       7.共享内存( shared memory ) :共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问。共享内存是最快的 IPC 方式,它是针对其他进程间通信方式运行效率低而专门设计的。它往往与其他通信机制,如信号两,配合使用,来实现进程间的同步和通信。
       8.套接字( socket ) : 套接口也是一种进程间通信机制,与其他通信机制不同的是,它可用于不同机器间的进程通信。
 

7.Linux性能监控命令
8.海量数据提取最大的k个数据:
        最大堆和最小堆的变化方式   堆排序的平均时间复杂度为nlogn
        最大堆最小堆的过程的时间复杂度为logn
9.死锁的四个必要条件
        1、互斥条件:一个资源每次只能被一个进程使用;
        2、请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放;
        3、不剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺;
        4、循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系;
10.冒泡排序和快速排序的思路
        冒泡排序:
       (1)  比较相邻的元素。如果第一个比第二个大,就交换他们两个。
        (2)对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。
        (3)针对所有的元素重复以上的步骤,除了最后一个。
        (4)持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
        快速排序:
        (1)首先设定一个分界值,通过该分界值将数组分成左右两部分
        (2)将大于或等于分界值的数据集中到数组右边,小于分界值的数据集中到数组的左边。此时,左边部分中各元素都小于或等于分界值,而右边部分中各元素都大于或等于分界值
        (3)然后,左边和右边的数据可以独立排序。对于左侧的数组数据,又可以取一个分界值,将该部分数据分成左右两部分,同样在左边放置较小值,右边放置较大值。右侧的数组数据也可以做类似处理
        (4)重复上述过程,可以看出,这是一个递归定义。通过递归将左侧部分排好序后,再递归排好右侧部分的顺序。当左、右两个部分各数据排序完成后,整个数组的排序也就完成了
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值