关于NCSI的标准介绍,我们可以参考DMTF的文档,链接:
https://www.dmtf.org/sites/default/files/standards/documents/DSP0222_1.1.0.pdf
https://www.dmtf.org/sites/default/files/standards/documents/DSP0222_1.2.0b.pdf

也可以参考下面这篇IBM曾经的文章,现在已经失传。

王俊元, 软件工程师, IBM
王寒芷, 软件工程师, IBM

简介: NCSI(Network Controller Sideband Interface)是一个由分布式管理任务组(Distributed Management Task Force, DMTF)定义的用于支持服务器带外管理的边带接口网络控制器的工业标准,由一个管理控制器和多个网络控制器组成。DMTF 为 NCSI 定义了完整的基于以太网的控制命令请求和应答标准,此外,NCSI 还具备单线程,超时重传等机制。本文结合NCSI标准,简单演示了在 Linux 网络协议栈中注册、初始化 NCSI 协议,并且利用 socket 接口实现一个完整的 NSCI 操作的过程。

引言

网络技术的飞速发展使得人们对于服务器的带外可管理性及可控制性提出了更高的要求。通过带外管理,工程师可以在任意地点通过网络连接到相应的服务器上,进行一系列的管理与维护,而不再需要长时间驻守在嘈杂的实验室环境中。NCSI(Network Controller Sideband Interface)就是一个由分布式管理任务组(Distributed Management Task Force, DMTF)定义的用于支持服务器带外管理的边带接口网络控制器的工业标准。

NCSI 的简单介绍

NCSI 的简单介绍

一般地,服务器的网络管理模块结构如图 1 所示:

它主要包括:一个管理控制器(Management Controller, MC),一个或多个(NCSI 的电气特性最多支持 4 个)网络控制器(Network Controller, NC)。网络控制器一方面连接了外部网络接口与内部主机接口,另一方面,又与管理控制器之间有一个带外接口。

通过带外接口的网络数据包主要分为两类:一类是在外部网络与管理控制器之间传输的普通数据包,网络控制器对于这类数据包只作转发处理;另一类是在管理控制器与网络控制器之间传输的携带控制信息的数据包,他们往往是管理控制器对网络控制器配置的一些修改操作,对于这类数据包,网络控制器需要做出相应的响应。而管理控制器与网络控制器之间的带外接口的电气性质以及通信协议,就是由 NCSI 来定义的。

此外,NCSI 还提供了相应的传输协议栈来保证这种带外管理。NCSI 的传输协议栈如图 2 所示:

从图 2 中可以看到:

  • 在 NCSI 的传输协议栈中,位于最底层的是物理层,NCSI 的物理层是基于 RMII 接口的;
  • 位于物理层之上的是数据链路层,NCSI的数据链路层是基于以太介质的;
  • NCSI 支持的位于数据链路层之上的协议主要有两种:一种是管理控制器与网络控制器之间交互的 NCSI命令协议,另一种是管理控制器与外部网络通信的网络数据协议,如:ARP 协议、DHCP 协议、NetBIOS协议等,它们只是被网络控制器在管理控制器和外部网络之间作转发处理。在本文中,我们着重讨论第一种协议,也就是控制命令协议。

NCSI 控制命令协议

NCSI 控制命令允许管理控制器初始化、规范化自己的 NCSI 接口流量,配置 NCSI 信道过滤规则以及监控网络控制器的运行状态。作为 NCSI 控制命令协议的主体,管理控制器是所有控制命令的发起者,而网络控制器则响应管理控制器发送的控制命令。

NCSI 实例号(IID)

所有通过 NCSI 命令发送的 NCSI 请求都有一个唯一的标识符 Instance ID(IID)。IID 是一个 8 比特长的标识序列。每个 NCSI 响应包的 IID 都等于所对应的 NCSI 请求包的 IID。通过使用 IID,可以有效地识别新的 NCSI 请求,提高 NCSI 请求与响应匹配的鲁棒性,并且区分新的 NCSI 请求与超时重传的 NCSI 请求。

网络控制器在收到标记有 IID 的 NCSI 请求时,会遵循如下的操作原则:

在响应的包的相应位置会标记有该 NCSI 响应对应的 NCSI 请求的 IID。

如果收到的 NCSI 请求的 IID 与之前收到的相同,则表明这是一个超时重发的 NCSI 请求。NCSI 标准规定,此时网络控制器必须对重发的 NCSI 请求作出响应。网络控制器可以根据具体的 NCSI 命令,返回前一次 NCSI 命令的执行结果,如果该执行结果在当前时刻还没有失效。或者,网络控制器也可以重新在当前时刻再执行一遍 NCSI 命令。

如果收到的 NCSI 请求的 IID 与之前收到的不同,则网络控制器必须将这个请求看成是一个新的 NCSI 请求。

对于一个被重新初始化的网络控制器而言,它所收到的第一个 NCSI 请求一定是一个新的请求,而不管他在没有被重新初始化前是否收到具有相同 IID 的 NCSI 请求。

对于管理控制器而言,它在处理 IID 时遵循如下原则:

每个新的 NCSI 请求实例必须有与之前不同的 IID。

如果一个 NCSI 请求需要被重传,则其 IID 必须与之前的 NCSI 请求的 IID 相同。

由于 NCSI 响应包的 IID 等于其对应的 NCSI 请求包的 IID,所以 IID 可以进一步被管理控制器用作确认某个特定的 NCSI 请求是否被响应的标志。

单线程机制

就目前而言,网络控制器只能以单线程的方式支持 NCSI 命令。也就是说,网络控制器一次只能够执行一个 NCSI 命令。只有当它对收到的某个 NCSI 请求发送了响应包之后,才能够继续接受下一个 NCSI 请求。

网络控制器的这种单线程机制使得管理控制器在对同一个网络控制器发送 NCSI 请求时也只能以单线程方式进行。当管理控制器向某个网络控制器发送了一个 NCSI 请求后,它必须保持等待状态,直到收到了网络控制器发出的 NCSI 响应或者超时重传为止。

超时重传机制

如果在 NCSI 命令超时的时间间隔内,管理控制器还没有收到网络控制器回复的 NCSI 响应,则管理控制器必须以相同的 IID 重发之前的 NCSI 请求。

管理控制器必须尝试 NCSI 请求至少 3 次,才能够报告网络控制器发生了错误。

在网络环境相对恶劣的情况下,可能管理控制器在收到之前发送的 NCSI 请求的响应的时候,已经超过了超时重发的时间间隔。在这种情况下,管理控制器会收到对于同一个 NCSI 请求的两个响应。管理控制器必须有相应的机制能够检测出这第二个 NCSI 响应,并且将它丢弃。

异步事件通告包

AEN(Asynchronous Event Notification)包是网络控制器在某些状态发生变化、且影响其接口正常工作的情况下向管理控制器主动发送的通告数据包。由于 NCSI 命令只是网络控制器处理的众多数据包中的一小部分,网络控制器的一系列事件都会影响到命令的正常执行。这些事件包括:链路状态变化、操作系统驱动加载及卸载、芯片复位等等。

网络控制器对哪些事件会向管理控制器发送 AEN 包是由管理控制器来定义的,管理控制器通过使用控制位(control bit),可以单独地定义网络控制器对各个事件的异步事件通告是否启用。

AEN 包是工作在 NCSI 请求 - 应答机制之外的一种 NCSI 包。也就是说,AEN 包既不是 NCSI 请求,也不是任意 NCSI 请求的响应。AEN 包没有应答,即使一个 AEN 包在传输的过程中丢失了,管理控制器也无从得知。

一个 AEN 包的 IID 始终为 0x00。

NCSI 包结构

NCSI 的以太网帧头

正如前文所述,NCSI 是基于以太介质的。所有的 NCSI 包都是封装在 IEEE 802.3 定义的以太网帧格式中的,即:任意一个 NCSI 包都被封装在 14 字节的以太网头及 4 字节的以太网尾中,如图 3 所示:

图 3. NCSI 包的以太帧格式

目的地址字段:

NCSI 以太帧的第 0 到 5 字节分别代表以太网目的地址的第 5 到 0 字节。由于传输 NCSI 命令的信道并没有被分配一个特定的
MAC 地址,所以 NCSI 以太帧的目的地址为广播地址(FF:FF:FF:FF:FF:FF)。

如果网络控制器收到了一个目的地址不是 FF:FF:FF:FF:FF:FF 的 NCSI 包,则它会直接丢弃该数据包并且返回一个错误响应。

源地址字段:

NCSI 以太帧的第 6 到 11 字节分别代表以太网源地址的第 5 到 0 字节。如果 NCSI
包来自于管理控制器,那么源地址字段可以为任意值。如果 NCSI 包来自于网络控制器,则源地址字段必须为 FF:FF:FF:FF:FF:FF。

类型字段:

NCSI以太帧的第 12、13 字节分别代表以太网类型的第 1、0 字节。对于NCSI 控制包而言,其类型字段为 0x88F8。

NCSI 控制包头

每个 NCSI 包(包括 NCSI 请求包、响应包以及 AEN 包)都有一个 16 字节长的控制包头,以大端在先顺序排列,如图 4 所示:

图 4. NCSI 控制包头格式

Management Controller ID(MC ID)字段

MC ID 字段 1 字节长,标识了 NCSI 包对应的管理控制器。在 NCSI 1.0.0a 版本中,该字节规定为 0x00。

网络控制器每收到一个管理控制器发出的 NCSI 请求时都必须将请求包中的 MC ID 字段拷贝到响应包的 MC ID 字段中。

Header Revision 字段

Header Revision 字段 1 字节长,标识了 NCSI 命令包头的版本号。在 NCSI 1.0.0a 版本中,该字节规定为
0x01.

IID 字段

IID 字段 1 字节长。正如上文所述,网络控制器可以用 IID 来辨别当前 NCSI
命令是一个新的请求还是一个超时重传的请求;管理控制器可以用 IID 来确认某个特定的 NCSI 请求是否得到了相应。

Command 字段

Command 字段 1 字节长,用于标识特定的 NCSI 命令请求与响应。每个 NCSI 请求命令都对应着 0x00 到 0x7F
之间唯一的一个命令号,而对该 NCSI 请求包的响应的命令号就是把 NCSI 请求的命令号的最高位置为 1,这样就建立了 128 个
NCSI 请求命令与相应的 128 个 NCSI 响应命令之间的一一对应关系。

Channel ID 字段

Channel ID 字段 1 字节长。每个 NCSI 管理控制器可以对应一个或者多个 package,这些 package
可以属于同一个网络控制器,也可以属于不同的网络控制器。每个 package 的内部又可以定义一个或者多个信道(channel)。所有的
NCSI 数据包都是在某个特定的 channel 中传输的,Channel ID 字段就标识了当前 NCSI 数据包所在的 channel。

Payload Length 字段

Payload Length 字段 12 比特长,标识了紧随 NCSI 包头之后的 NCSI 载荷的长度。

Reserved 字段

图中标有 Reserved 的区域均为保留字段,通常被置为 0。

NCSI 控制包载荷

NCSI 控制包载荷的数据都是按照大端在先的顺序排列的,包括数据、载荷填充、校验和以及以太包填充 4 部分,如图 5 所示:

数据(Data)部分:

NCSI 请求不含 Data 部分。

每个 NCSI 响应都有 2 字节的响应值和 2 字节的原因值。对于某些 NCSI 命令的响应,还有一定长度的附加信息。

载荷填充部分:

如果 NCSI 的 Data 部分长度不是 4 字节的整数倍,那么就需要将其填充为 4 字节的整数倍。所有的填充值均为 0x00.

校验和部分:

校验和部分 4 字节长。管理控制器和网络控制器可以利用校验和部分来对 NCSI 包进行校验,也可以将校验和部分设为全 0,从而表明该
NCSI 包不需要校验。

以太包填充部分:

根据 IEEE 802.3 标准,所有的以太帧长度必须大于 64 字节,也就是说,NCSI 包头和 NCSI 载荷的长度之和必须大于 46
字节。事实上,大部分的 NCSI 包都无法满足这一条件。因此,几乎所有的 NCSI 包的末尾都需要作一定长度的填充。

AEN 包格式

NCSI 的 AEN 包格式如图 6 所示:

图 6. AEN 包格式

发送 AEN 包的网络控制器需要在 NCSI 包头的 Channel ID 字段里标识发生相应事件的 channel 号。

AEN 包的 NCSI 头的 IID 字段始终为 0x00,command 字段始终为 0xFF,Payload Length 字段始终为 0x04,也就是说 AEN 包的 NCSI 载荷长度为 4。

AEN 包的 NCSI 载荷中 3 字节为保留字段,另外一个字节为 AEN 类型字段,对应的含义如表 1 所示:

AEN类型值   含义
0x00    链路状态发生了改变
0x01    需要对网络控制器进行配置
0x02    网络控制器驱动的状态发生了改变
0x03 ~ 0x7F 保留
0x80 ~ 0xFF 各厂商自定义的 AEN 事件

NCSI 在 Linux 上的简单实现

硬件支持

要实现 NCSI,首先需要选择支持 NCSI 的 NIC,目前大部分网络芯片厂商都有支持 NCSI 的产品,比如 Broadcom 的 BCM57710,Intel 的 Intel82576 等。

在 Linux 网络协议栈中初始化 NCSI 协议族

在 Linux 的网络协议栈中初始化 NCSI 协议族需要了解 Linux 的网络协议栈,这不是本文讨论的重点,本节只是简单介绍在 Linux 网络协议栈的三个层面(Socket 层、Sock 层和 sk_buff 层)上初始化 NCSI 接口。之所以只是介绍这三层,是因为 socket{}、sock{}、sk_buff{} 是 Linux 网络协议栈中最重要的数据结构,也是数据流的连接通道。比如,发送报文时,数据会由 socket{} 通过相应的 proto_ops{} 把数据传给 sock{},sock{} 又通过 proto{} 把数据传到 sk_buff;反过来,当收到报文时,sk_buff{} 通过 net_protocol{} 把数据传给 sock{},后者又通过 proto{} 把数据传给 socket{},socket{} 最后把数据传给用户层,有关这方面具体详细细节在这里不做过多赘述。

Socket 层,注册 net_proto_family 结构体

清单 1. 注册 net_proto_family 结构体到全局数组 net_families 中

#define PF_NCSI    27  /* NCSI Address Family */ static struct net_proto_family ncsi_family_ops = { .family =  PF_NCSI, .create =  ncsi_create, .owner  =  THIS_MODULE, }; sock_register(&ncsi_family_ops);

Sock 层,填充 proto_ops 结构体,该结构体的成员变量是一些函数指针,分别对应了 NCSI 操作的函数。

清单 2. 填充 proto_ops 结构体

 static struct proto_ops ncsi_ops = { .family =  PF_NCSI, .owner =  THIS_MODULE, .release =  ncsi_release, .bind =    sock_no_bind, .connect =  sock_no_connect, .socketpair =  sock_no_socketpair, .accept =  sock_no_accept, .getname =  sock_no_getname, .poll =    sock_no_poll, .ioctl =  sock_no_ioctl, .listen =  sock_no_listen, .shutdown =  sock_no_shutdown, .setsockopt =  sock_no_setsockopt, .getsockopt =  sock_no_getsockopt, .sendmsg =  ncsi_sendmsg, .recvmsg =  ncsi_recvmsg, .mmap =    sock_no_mmap, .sendpage =  sock_no_sendpage, };

sk_buff 层,实现从 NIC 接收 NCSI packet 的功能,其中 ncsi_rcv 是从 NIC 中接收 RAW packet 的接口。

清单 3. 实现从 NIC 接收 NCSI packet 的功能

 #define NCSI_PROTOCOL 0x88F8 static struct packet_type ncsi_packet_type = { .type =    __constant_htons(NCSI_PROTOCOL), .func =    ncsi_rcv, }; dev_add_pack(&ncsi_packet_type);

利用套接字 socket 实现 NCSI 的操作

在 Linux 的网络协议栈中初始化了 NCSI socket 的三元组:< 地址族,类型,具体协议 >,也正好是调用 socket 系统函数的 3 个参数。内核中这 3 个数据结构,就可以创建 sock{} 结构。

首先,在利用套接字实现 NCSI 操作之前,为了提高程序的通用性和易读性、减少不一致性,需要对 NCSI 协议族进行宏定义:

清单 4. 对 NCSI 协议族进行宏定义

 #define AF_NCSI    27  /* NCSI 地址族定义 */

其次,为了便于对 NCSI 包头进行整体性操作,这里根据前文所述的 NCSI 包格式,定义了 NCSI 的包头结构 ncsihdr:

清单 5. NCSI 包头结构的定义

/* NCSI 包头结构的定义 */ struct ncsihdr { unsigned char mc_id; unsigned char hdr_rev; unsigned char reserved0; unsigned char cmd_iid; unsigned char cmd; unsigned char chnl_id; unsigned short payload_len; unsigned int reserved2; unsigned int reserved3;  };

从根本上说,NCSI 主要包括 4 种原子操作:创建 NCSI socket、关闭 NCSI socket、向已创建的 NCSI socket 发送 NCSI 命令以及从已创建的 NCSI socket 获得 NCSI 响应。一个最简单的 NCSI 命令操作流程如图 7 所示:

其他任意操作都可以通过使用这 4 种原子操作的组合来实现。为简单起见,本文仅对这 4 中最基本的 NCSI 操作给出了在 linux 下的相应实现,而对于由这 4 种操作引申而出的其它复杂操作就不做过多的赘述了。
(1) 创建 NCSI socket:

清单 6. 创建 NCSI socket

 int OpenNCSISocket () { // 调用 socket 函数创建一个能够进行网络通信的套接字:协议族为 AF_NCSI,套接字类型为 SOCK_RAW sd = socket(AF_NCSI, SOCK_RAW, 0); if (sd < 0) { cout << "NCSI socket creation failed" << endl; return -1; }    return sd; }

(2) 关闭 NCSI socket:

清单 7. 关闭 NCSI socket

             int CloseNCSISocket(int sd) { close(sd);    // 调用 close 函数关闭已创建的套接字return 0; }

(3) 向已创建的 NCSI socket 发送 NCSI 命令:

清单 8. 向已创建的 NCSI socket 发送 NCSI 命令

 int SendRawNCSIPacket( int sd,      // 已创建的 NCSI socket int Port_Num,    //NCSI 命令发送到的以太网接口号unsigned char cmd,    //NCSI 命令号unsigned char channel_id,  // 承载 NCSI 命令的信道号unsigned char *pu8Data,  // 指向 NCSI 载荷的指针unsigned short data_length//NCSI 载荷的长度) { int status; struct ncsihdr *ncsih;      //NCSI 包头struct iovec xmit_iovec[2];    // 创建 linux I/O 向量 iovec 结构数组struct msghdr xmit_message;     // 创建 linux 信息头 msghdr 结构数组unsigned char pkt_buffer[60];      // 发送缓冲区unsigned char *ncsi_payload ;    //NCSI 载荷指针// 封装以太网帧头memset(pkt_buffer, 0, 60); memset(pkt_buffer, 0xff, 12);      // 目的地址和源地址均为 0xFF FF FF FF FF FF pkt_buffer[12] = 0x88; pkt_buffer[13] = 0xf8;            // 以太网帧头类型字段为 0x88f8,表示 NCSI 命令// 封装 NCSI 包头ncsih = (struct ncsihdr *) (pkt_buffer+14); ncsih->mc_id = 0x0;      // 设置管理控制器 ID 为 0x0 ncsih->hdr_rev = 0x1;      // 设置 NCSI 头版本号围 0x1 ncsih->cmd_iid = inciid();     // inciid() 是一个函数,用于获得当前发送数据包的 instance id ncsih->cmd = cmd;      // 设置 NCSI 命令的命令号ncsih->chnl_id = channel_id;    // 设置 NCSI 命令传输的信道号// 设置 NCSI 载荷的长度。由于网络字节序使用的都是大端模式,所以要调用 htons 进行相应的转换ncsih->payload_len = htons(data_length);// 封装 NCSI 载荷ncsi_payload = (unsigned char *)(pkt_buffer + 14 + sizeof(struct ncsihdr)); if ( (pu8Data!=NULL) && (data_length!=0) ) { memcpy(ncsi_payload, pu8Data, data_length); } // 封装 xmit_message xmit_message.msg_name = NULL; xmit_message.msg_namelen = 0; xmit_message.msg_iov = xmit_iovec; xmit_message.msg_iov[0].iov_base = (void *)&Port_Num; xmit_message.msg_iov[0].iov_len = sizeof(int); xmit_message.msg_iov[1].iov_base = (void *)pkt_buffer; xmit_message.msg_iov[1].iov_len = 60; xmit_message.msg_iovlen = 2; xmit_message.msg_control = NULL; xmit_message.msg_controllen = 0; xmit_message.msg_flags = 0; // 调用 linux 的 sendmsg 发送 NCSI 请求status = sendmsg(sd, &xmit_message, 0); return status; }

(4) 从已创建的 NCSI socket 获得 NCSI 响应:

清单 9. 从已创建的 NCSI socket 获得 NCSI 响应

 int RecvRawNCSIPacket( int sd,        // 已创建的 NCSI socket unsigned char *pu8NCSIpacket,  // 用于存放接收数据的缓冲区int buf_size,        // 接收缓冲区的大小int *Port_Num,      // 接收 NCSI 响应的以太网接口号int wait_time        // 等待时间,单位毫秒) { int status; struct msghdr recv_message;    // 创建 linux 信息头 msghdr 结构数组struct iovec recv_iovec[3];    // 创建 linux I/O 向量 iovec 结构数组if ( (NULL == pu8NCSIpacket) || (0 == buf_size ) return -1; // 封装 recv_message recv_message.msg_name = NULL; recv_message.msg_namelen = 0; recv_message.msg_iov = recv_iovec; recv_message.msg_iov[0].iov_base = (void *)&wait_time; recv_message.msg_iov[0].iov_len = sizeof(int); recv_message.msg_iov[1].iov_base = (void *) pu8NCSIpacket; recv_message.msg_iov[1].iov_len = buf_size; recv_message.msg_iov[2].iov_base = (void *)Port_Num; recv_message.msg_iov[2].iov_len = sizeof (int *); recv_message.msg_iovlen = 3; recv_message.msg_control = NULL; recv_message.msg_controllen = 0; recv_message.msg_flags = 0; // 调用 linux 的 recvmsg 接收 NCSI 响应status = recvmsg(sd, &recv_message, 0); return status; }

总结

本文结合 DMTF 的 NCSI 标准,对 NCSI 的控制命令协议以及包结构作了详细的描述,并在此基础之上,进一步简单演示了在 Linux 网络协议栈中注册、初始化 NCSI 协议,并且利用 socket 接口实现一个完整的 NSCI 操作的过程,希望能够为使用 NCSI 标准进行带外管理的网络管理人员及 linux 网络编程爱好者提供有益的参考。

【Linux】 浅谈 NCSI 及其在 Linux 上的实现相关推荐

  1. 计算机仿真在机械应用,浅谈计算机仿真在机械上的应用[精选].doc

    浅谈计算机仿真在机械上的应用[精选] 浅谈计算机仿真在机械上的应用 李思宏 (重庆交通大学,重庆402247) 摘要:如今计算机仿真技术在机械上有着广泛的应用,计算机仿真已然成为热门.本文用综述的形式 ...

  2. 浅谈WebAssmebly,在浏览器上进行图像处理

    浅谈WebAssmebly,在浏览器上进行图像处理 自从2008年各大浏览器为JavaScript执行引擎加入JIT(Just in Time, 即时编译器)以来,JavaScript在浏览器的执行性 ...

  3. 浅谈身为小白学习Linux系统的四点实用建议

    2019独角兽企业重金招聘Python工程师标准>>> 游戏.办公.安全,可以总结为是方便当代人们在生活中的刚需,我们大都是这些服务的使用者,而把单个功能整合起来那就必须谈到互联网, ...

  4. 浅谈缓冲区溢出之栈溢出上

    有段时间没有用windows了,刚一开机又是系统补丁更新.匆匆瞥了一眼看到了"内核缓冲区溢出漏洞补丁"几个字眼.靠,又是内核补丁.打完这个补丁后MD的内核符号文件又得更新了.于是抱 ...

  5. 浅谈游戏服务器---功能模块上来看

    游戏服务器在网游上的作用不容考虑,游戏能做大到什么程度,还是有很大的依靠的,这篇文章先从功能模块的角度来谈一个完善的游戏服务器需要实现哪.     一:游戏服务器的作用:连接各个网游客户端,实现各客户 ...

  6. Linux培训教程 浅谈:PHP在linux上执行外部命令(整理)

    一.PHP中调用外部命令介绍 二.关于安全问题 三.关于超时问题 四.关于PHP运行linux环境中命令出现的问题 一.PHP中调用外部命令介绍 在PHP中调用外部命令,可以用,1>调用专门函数 ...

  7. Linux 浅谈代码打印到终端的缓冲区(进度条程序)

    我们知道printf是向终端显示打印数据,是我们想要看到程序的结果,而在linux系统下一切皆文件,在终端显示是要有显示器设备的,在linux下把显示器设备当做文件进行操作,将数据写入到显示器设备文件 ...

  8. 浅谈VMware下安装Linux的网络设置 -- NAT

    最近因为学习的需要,需要虚拟搭建一个Linux服务器.为什么说虚拟?因为我们并不是搭建一台真正的服务器(没有在IBM或是HP大型机或是刀架上装系统),只是想在家用机上装上Linux系统做些实验.写这篇 ...

  9. linux 目录的粘滞位,Linux浅谈SUID,SGID,Sticky粘滞位对目录以及文件的相关作用

    我们知道在Linux中,root管理员的权限是很大的,能够支持执行绝大部分程序以及命令进而对文件进行相对应的修改,写入.当然这些作用只能体现在root管理员上.但是有一个现象,有些普通用户是可以通过p ...

  10. deepin linux 2014安装,2014.2版本的Deepin虚拟机安装浅谈(就是深度Linux)

    最近更新:3rd 1月, 2015 依稀记得我在七年前开始追开源,那时候有Everest,有红旗,还有银河麒麟.当时觉得中文Linux发行版前途一片大好,自己也曾混迹于Linux-ren,百度贴吧百度 ...

最新文章

  1. 论文作者串通抱团、威胁审稿人,ACM Fellow炮轰「同行评审」作弊
  2. ES6常用新特性---笔记一
  3. Ansible基础入门
  4. python实现多线程的三种方法threading.Thread(模块)的继承实现和函数实现;以及concurrent.futures模块的线程池实现
  5. hadoop NameNode HA 和ResouceManager HA
  6. 用批处理修复 win10 无法升级的问题
  7. C语言试题四十八之该函数可以统计一个长度为2的字符串在另一个字符串中出现的次数。
  8. jquery上传图片_MVC 上传图片,裁剪头像
  9. ADC的指标详细定义,SNR,以下内容无关: -------------------------------------------分割线----------------SNDR,SFDR,THD等
  10. 天正服务器修改,天正修改服务器地址
  11. 概率初步入门(含贝叶斯公式,全概率公式)
  12. 综述:图像风格化算法最全盘点 | 内附大量扩展应用
  13. 52亿美元!Uber迎来有史以来最大季度亏损和最慢营收增长
  14. 【略有料】JDBC Statements, PreparedStatement和CallableStatement语句
  15. 程序员开发了自己的产品怎样推广?说一说我的免费在线客服系统推广经验
  16. 微信小程序如何引入直播组件?
  17. 通达信波段王指标公式主图_通达信波段专用主图指标公式
  18. Gzip的动态压缩和静态压缩详解
  19. android音频编辑之音频合成
  20. 2011, 完全用 GNU/Linux 工作

热门文章

  1. pop3邮箱服务器地址,常用的邮箱服务器(SMTP、POP3)地址、端口
  2. Android 关于推送通知还需要一些其他的设置问题,最新高频Android笔试题分享
  3. Unable to instantiate application 解决办法
  4. 24小时“凶宅试睡直播”去“凶”,阿里拍卖为卖凶宅有点拼
  5. ccs定义的函数不变色_ccs使用问题及解决办法
  6. HDU 5857 Median(找中位数)
  7. 【Python入门教程】第35篇 查找元素的位置
  8. python弧度制转角度制_弧度制与角度制转换
  9. 广东省计算机学校,广东省计算机基础练习平台(高校版)安装设置方法
  10. 八,分隔符,其他符号和数据的讲解