美文网首页
信号打断read()函数、accept()函数

信号打断read()函数、accept()函数

作者: StevenHD | 来源:发表于2020-12-07 00:03 被阅读0次

    一、信号打断read()函数

    • read()函数如果阻塞地读,很容易就会被信号打断
      如果被信号打断,返回的错误码errno则是EINTR,然而无所谓,我们被信号打断并不影响什么,continue并且取消关闭fd,进入下一次循环即可——
    图示代码

    二、信号打断accept()函数

    • 先打开服务器后,不启动客户端,那么现在就阻塞在accept()这个地方
    • 打开服务器后,客户端启动完,就进入到了read()函数中

    被信号打断并不可怕,我们只要设置成,万一被打断了,重启一次就行,这样就没有事

    accept()被打断后的处理
    我们可以让它continue,另一种就是设置【信号中的RESTART】——
    信号中的重启
    • read函数中的信号处理——


      图示代码

    三、复习review

    复习大纲
    复习大纲2

    四、错误值封装

    • 一行的结束标志是/n
    • 字符串的结束标志是/0

    先从缓存中读取数据,然后读取文件描述符(套接字)中的数据

    五、多进程服务器

    多进程模型1 多进程模型2
    • 轮询的坏处:如果没有实际的数据进入,那么CPU就是一直空转,占用CPU的使用

    • 现如今服务器的缺点,不能处理多个客户端的连接,因为accept()完成后,会进入read()函数,这个时候第二个客户端连接进来后只能进入accpe()的队列中,但是服务器还是在read()函数中,没有进入到accept()那个函数,那么就不能处理另一个客户端的三次握手

    • 多进程服务器模型,原先的进程只负责accept(),至于读取数据则是fork()出一个子进程来处理,新来一个客户端的连接就fork()一次子进程——

    • fork()之后文件描述符表也会被复制,因为整个PCB都会被复制,PCB中包含文件描述符表。(fork()之后file结构体并没有复制过来,只是新的FD对应的新的指针指向了同一个file结构体

    子进程中的client_fd是从父进程中拷贝过来的,使用这个复制过来的套接字client_fd并读取数据,并且和父进程中的client_fd指向的是同一个套接字socket。

    • 将fork()放到accept()函数的下面,然后将之前的读取数据都放在子进程中,父进程直接continue,进行下一次accept()即可。
    图示代码
    图示代码2
    • 但是上述代码会产生僵尸进程,我们没有去回收子进程
    • 之前回收子进程的方法有wait()和waitpid(),但是现在父进程已经阻塞在accept()了(每接收完一个请求就回到accept()那里),不能再让它阻塞在wait()那里接收子进程的退出了。

    所以除了阻塞轮询的方式,我们只能使用【信号waitpid()】这种方式了——

    这样就不会出现僵尸进程了
    这样就不会出现僵尸进程了
    为什么使用SIGCHLD这个信号呢?因为当子进程退出的时候会发给父进程信号SIGCHLD,所以我们需要捕捉的就是这个信号。
    • 100个子进程同时退出,就会给父进程发100个信号
    • 文件描述符表通过fork()直接复制过来,是一个浅拷贝,并没有生成新的file结构体

    因为fork()后不论是listen_fd还是client_fd都会被复制,但是listen_fd并没有再被使用,所以要在一开始就关闭掉listen_fd——

    图示代码关闭listen_fd
    • 当然了,因为父进程中没有再用到client_fd,所以在fork()后,也要手动关闭client_fd,因为只有这样才不会造成内存泄漏,只靠子进程那里关闭只会让引用计数-1,并不会真的关闭,除非父进程也退出——
    图示代码——父进程也要关闭client_fd

    5.1 服务器不光读也可以写消息给客户端

    • 服务器的代码(将接收到的字符串变成大写)——
    增加了Write()函数
    • 客户端的代码——
    增加了write()和read()函数

    多进程模型的好处:可以不断地创建子进程来处理连接请求,可以通过ulimit -a来查看可以创建多少个进程数量

    最大进程数量
    • 也可以去系统文件改写这个数值

    虽然多进程都是fork出来的,但是比如buf这种缓存区中接收到的内容,因为读时共享,写时复制的原则,buf区中接收到的数据一定是不一样,那么系统会新分配一个内存页的。

    相关文章

      网友评论

          本文标题:信号打断read()函数、accept()函数

          本文链接:https://www.haomeiwen.com/subject/nxuowktx.html