天天看点

第五十二篇 操作系统简史——多道技术第五十二篇 操作系统简史——多道技术

目录

  • 第五十二篇 操作系统简史——多道技术
    • 一、操作系统
      • 1.操作系统简介
      • 2.操作系统作用
      • 3.操作系统与应用程序的区别
    • 二、操作系统发展历史
      • 1.第一代计算机(1940~1955):真空管和穿孔卡片
      • 2.第二代计算机(1955~1965):晶体管和批处理系统
      • 3.第三代计算机(1965~1980):集成电路芯片和多道程序设计
      • 4.第四代计算机(1980~至今):个人计算机
    • 三、多道技术
    • 四、setsockopt的作用

第五十二篇 操作系统简史——多道技术

一、操作系统

1.操作系统简介

1.操作系统位于应用软件与硬件设备之间,本质上也是一个软件

2.由系统内核(管理所有硬件资源)与系统接口(提供给程序员使用的接口)组成

2.操作系统作用

1.为用户屏蔽了复杂繁琐的硬件接口,为应用程序提供了清晰易用的系统接口(有了这些接口,程序员就不用直接与硬件打交道了)

2.操作系统将应用程序对硬件资源的竞争变成有序的使用

3.操作系统与应用程序的区别

1.操作系统是受保护的:无法被用户修改,应用程序可以被卸载

2.操作系统规模很大:Linux或widows源代码都在五百万行以上。这仅仅是内核,不包括用户程序,如GUI,库以及基本应用软件(如windows Explorer等),很容易就能达到这个数量的10倍或者20倍之多

3.长寿:由于操作系统源码量巨大,编写是非常耗时耗力的,一旦完成,操作系统所有者便不会轻易的放弃或重写,但是可以在原有基础上改进,因此基本上可以把windows95/98/Me看出一个操作系统

二、操作系统发展历史

1.第一代计算机(1940~1955):真空管和穿孔卡片

2.第二代计算机(1955~1965):晶体管和批处理系统

3.第三代计算机(1965~1980):集成电路芯片和多道程序设计

4.第四代计算机(1980~至今):个人计算机

1.第四代也就是我们常见的操作系统,大多是具备图形化界面的,例如:Windows,macOS ,CentOS等

2.由于采用了IC设计,计算机的体积下降,性能增长,并且成本以及可以被普通消费者接受,而第三代操作系统大都需要进行专业的学习才能使用,于是各个大佬公司开始开发那种不需要专业学习也可以快速上手的操作系统,即上述操作系统

3.它们都是用了GUI 图形化用户接口,用户只需要通过鼠标点击拖拽界面上的元素即可完成大部分操作

4.GUI和UI都是用于可视化的

三、多道技术

1.多道技术中的多道指的是多个程序,多道技术的实现是为了解决多个程序竞争或者说共享同一个资源(比如cpu)的有序调度问题,解决方式即多路复用,多路复用分为时间上的复用和空间上的复用

2.空间上的复用:将内存分为几部分,每个部分放入一个程序,这样,同一时间内存中就有了多道程序

3.空间上的复用最大的问题是:程序之间的内存必须分割,这种分割需要在硬件层面实现,由操作系统控制。如果内存彼此不分割,则一个程序可以访问另外一个程序的内存。首先丧失的是安全性,比如你的qq程序可以访问操作系统的内存,这意味着你的qq可以拿到操作系统的所有权限;其次丧失的是稳定性,某个程序崩溃时有可能把别的程序的内存也给回收了,比方说把操作系统的内存给回收了,则操作系统崩溃

四、setsockopt的作用

获取或者设置与某个套接字关联的选 项。选项可能存在于多层协议中,它们总会出如今最上面的套接字层。当操作套接字选项时,选项位于的层和选项的名称必须给出。为了操作套接字层的选项,应该 将层的值指定为SOL_SOCKET。为了操作其他层的选项,控制选项的合适协议号必须给出。比如,为了表示一个选项由TCP协议解析,层应该设定为协议 号TCP

參数:

sock:将要被设置或者获取选项的套接字。

level:选项所在的协议层。

optname:须要訪问的选项名。

optval:对于getsockopt(),指向返回选项值的缓冲。对于setsockopt(),指向包括新选项值的缓冲。

optlen:对于getsockopt(),作为入口參数时,选项值的最大长度。作为出口參数时,选项值的实际长度。对于setsockopt(),现选项的长度。

返回说明:

成功运行时,返回0。失败返回-1,errno被设为下面的某个值

EBADF:sock不是有效的文件描写叙述词

EFAULT:optval指向的内存并不是有效的进程空间

EINVAL:在调用setsockopt()时,optlen无效

ENOPROTOOPT:指定的协议层不能识别选项

ENOTSOCK:sock描写叙述的不是套接字

參数具体说明:

level指定控制套接字的层次.能够取三种值:

1)SOL_SOCKET:通用套接字选项.

2)IPPROTO_IP:IP选项.

3)IPPROTO_TCP:TCP选项. 

optname指定控制的方式(选项的名称),我们以下详解 

optval获得或者是设置套接字选项.依据选项名称的数据类型进行转换 

选项名称        说明                  数据类型

            SOL_SOCKET

SO_BROADCAST      同意发送广播数据            int

SO_DEBUG        同意调试                int

SO_DONTROUTE      不查找路由               int

SO_ERROR        获得套接字错误             int

SO_KEEPALIVE      保持连接                int

SO_LINGER        延迟关闭连接              struct linger

SO_OOBINLINE      带外数据放入正常数据流         int

SO_RCVBUF        接收缓冲区大小             int

SO_SNDBUF        发送缓冲区大小             int

SO_RCVLOWAT       接收缓冲区下限             int

SO_SNDLOWAT       发送缓冲区下限             int

SO_RCVTIMEO       接收超时                struct timeval

SO_SNDTIMEO       发送超时                struct timeval

SO_REUSERADDR      同意重用本地地址和port         int

SO_TYPE         获得套接字类型             int

SO_BSDCOMPAT      与BSD系统兼容              int

            IPPROTO_IP

IP_HDRINCL       在数据包中包括IP首部          int

IP_OPTINOS       IP首部选项               int

IP_TOS         服务类型

IP_TTL         生存时间                int

            IPPRO_TCP

TCP_MAXSEG       TCP最大数据段的大小           int

TCP_NODELAY       不使用Nagle算法             int

返回说明:

成功运行时,返回0。失败返回-1,errno被设为下面的某个值

EBADF:sock不是有效的文件描写叙述词

EFAULT:optval指向的内存并不是有效的进程空间

EINVAL:在调用setsockopt()时,optlen无效

ENOPROTOOPT:指定的协议层不能识别选项

ENOTSOCK:sock描写叙述的不是套接字

SO_RCVBUF和SO_SNDBUF每一个套接口都有一个发送缓冲区和一个接收缓冲区,使用这两个套接口选项能够改变缺省缓冲区大小。

// 接收缓冲区

int nRecvBuf=321024; //设置为32K

setsockopt(s,SOL_SOCKET,SO_RCVBUF,(const char)&nRecvBuf,sizeof(int));

//发送缓冲区

int nSendBuf=321024;//设置为32K

setsockopt(s,SOL_SOCKET,SO_SNDBUF,(const char)&nSendBuf,sizeof(int));

注意:

当设置TCP套接口接收缓冲区的大小时,函数调用顺序是非常重要的,由于TCP的窗体规模选项是在建立连接时用SYN与对方互换得到的。对于客户,O_RCVBUF选项必须在connect之前设置;对于server,SO_RCVBUF选项必须在listen前设置。
           

结合原理说明:

1.每一个套接口都有一个发送缓冲区和一个接收缓冲区。 接收缓冲区被TCP和UDP用来将接收到的数据一直保存到由应用进程来读。 TCP:TCP通告还有一端的窗体大小。 TCP套接口接收缓冲区不可能溢出,由于对方不同意发出超过所通告窗体大小的数据。 这就是TCP的流量控制,假设对方无视窗体大小而发出了超过窗体大小的数据,则接 收方TCP将丢弃它。 UDP:当接收到的数据报装不进套接口接收缓冲区时,此数据报就被丢弃。UDP是没有流量控制的;快的发送者能够非常easy地就淹没慢的接收者,导致接收方的UDP丢弃数据报。
    2.我们常常听说tcp协议的三次握手,但三次握手究竟是什么,其细节是什么,为什么要这么做呢?
    第一次:client发送连接请求给server,server接收;
    第二次:server返回给client一个确认码,附带一个从server到client的连接请求,客户机接收,确认client到server的连接.
    第三次:客户机返回server上次发送请求的确认码,server接收,确认server到client的连接.
    我们能够看到:
    1. tcp的每一个连接都须要确认.
    2. client到server和server到client的连接是独立的.
    我们再想想tcp协议的特点:连接的,可靠的,全双工的,实际上tcp的三次握手正是为了保证这些特性的实现.




    3.setsockopt的使用方法
           

1.closesocket(一般不会马上关闭而经历TIME_WAIT的过程)后想继续重用该socket:

BOOL bReuseaddr=TRUE;

setsockopt(s,SOL_SOCKET ,SO_REUSEADDR,(const char*)&bReuseaddr,sizeof(BOOL));

  1. 假设要已经处于连接状态的soket在调用closesocket后强制关闭,不经历TIME_WAIT的过程:

    BOOL bDontLinger = FALSE;

    setsockopt(s,SOL_SOCKET,SO_DONTLINGER,(const char*)&bDontLinger,sizeof(BOOL));

3.在send(),recv()过程中有时因为网络状况等原因,发收不能预期进行,而设置收发时限:

int nNetTimeout=1000;//1秒

//发送时限

setsockopt(socket,SOL_S0CKET,SO_SNDTIMEO,(char )&nNetTimeout,sizeof(int));

//接收时限

setsockopt(socket,SOL_S0CKET,SO_RCVTIMEO,(char )&nNetTimeout,sizeof(int));

4.在send()的时候,返回的是实际发送出去的字节(同步)或发送到socket缓冲区的字节

(异步);系统默认的状态发送和接收一次为8688字节(约为8.5K);在实际的过程中发送数据

和接收数据量比較大,能够设置socket缓冲区,而避免了send(),recv()不断的循环收发:

// 接收缓冲区

int nRecvBuf=321024;//设置为32K

setsockopt(s,SOL_SOCKET,SO_RCVBUF,(const char)&nRecvBuf,sizeof(int));

//发送缓冲区

int nSendBuf=321024;//设置为32K

setsockopt(s,SOL_SOCKET,SO_SNDBUF,(const char)&nSendBuf,sizeof(int));

  1. 假设在发送数据的时,希望不经历由系统缓冲区到socket缓冲区的拷贝而影响

    程序的性能:

    int nZero=0;

    setsockopt(socket,SOL_S0CKET,SO_SNDBUF,(char *)&nZero,sizeof(nZero));

6.同上在recv()完毕上述功能(默认情况是将socket缓冲区的内容复制到系统缓冲区):

int nZero=0;

setsockopt(socket,SOL_S0CKET,SO_RCVBUF,(char *)&nZero,sizeof(int));

7.一般在发送UDP数据报的时候,希望该socket发送的数据具有广播特性:

BOOL bBroadcast=TRUE;

setsockopt(s,SOL_SOCKET,SO_BROADCAST,(const char*)&bBroadcast,sizeof(BOOL));

8.在client连接server过程中,假设处于非堵塞模式下的socket在connect()的过程中能够设置connect()延时,直到accpet()被呼叫(本函数设置仅仅有在非堵塞的过程中有显著的作用,在堵塞的函数调用中作用不大)

BOOL bConditionalAccept=TRUE;

setsockopt(s,SOL_SOCKET,SO_CONDITIONAL_ACCEPT,(const char*)&bConditionalAccept,sizeof(BOOL));

9.假设在发送数据的过程中(send()没有完毕,还有数据没发送)而调用了closesocket(),曾经我们一般採取的措施是"从容关闭"shutdown(s,SD_BOTH),可是数据是肯定丢失了,怎样设置让程序满足详细应用的要求(即让没发完的数据发送出去后在关闭socket)?

struct linger {

u_short l_onoff;

u_short l_linger;

};

linger m_sLinger;

m_sLinger.l_onoff=1;//(在closesocket()调用,可是还有数据没发送完成的时候容许逗留)

// 假设m_sLinger.l_onoff=0;则功能和2.)作用同样;

m_sLinger.l_linger=5;//(容许逗留的时间为5秒)

setsockopt(s,SOL_SOCKET,SO_LINGER,(const char*)&m_sLinger,sizeof(linger));

转载于:https://www.cnblogs.com/itboy-newking/p/11185339.html

继续阅读