linuxifa
❶ 从ip addr add和ifconfig的区别看linux网卡ip地址的结构
如果你非常理解网络协议的原理以及网络的分层架构那么我想你就不会有这个问题,实际上,每一个网卡设备都有一个mac地址,但是却可 以有多个网络层地址,比如IP地址,然而这个事实无法很好地像用户提供操作接口,所以就引出了ip别名(IP aliases)和辅助ip(secondary IP addresses)的概念。其实很容易理解这个事实,按照分层的思想,下层总是为上层服务,也就是为上层提供舞台,上层利用下层的服务,而不必让下层知 道自己的情况,如果一个拥有合理mac地址的网卡没有配置网络层地址(比如IP地址)这件事合理的话,那么为这个设备配置多个IP地址也是合理的,正好像 一个ip可以对应多个应用层端口一样,也就是说,下层对上层总是一对多的关系,在分层架构中这种关系是合理的。下面我们就看一下linux的网卡的ip地 址结构。刚才说了在linux中,一个网卡可以有多个IP,那么这多个ip有什么关系呢?其实这些ip组成了一个吊链结构,所谓吊链结构就是一些节点链接 成一条链,然后每个节点带有自己的一条链
每个节点代表的ip地址标识一个网段,这个节点的ip就是这个网段的 Primary地址,它下面所带的ip就是这个网段的Secondary地址,也就是说一个网卡可以带有各个节点所带链表长度之和个ip地址,而且这些 ip不是线形的,而是上述的吊链结构。我们看一下这么做有什么好处。玩过Cisco路由器的朋友可能都知道有个Secondary IP的概念,这个特性可以创建逻辑子网,也就是说在一个物理网口上连接两个子网,这咋看起来好像不可思议,其实很简单,比如这个网口接到一台交换机上,如 果这个网口没有配置Secondary IP的话,那么这台交换机只能连接一个网段的主机,比如192.168.1.1/24,但是,如果它配置了Secondary IP,那么就可以连接两个网段的主机,比如192.168.1.1/24和10.0.0.1/24,道理就是这么简单,但是却很有用,该机制可以被路由汇 总策略所使用。注意上面这个例子中的Secondary IP不是这里说的linux的Secondary address,在linux中恰恰相反,只要一个网卡上配置的ip不是一个网段的,那么都是Primary IP,就是吊链结构中上面的那条主链中的IP,linux中的Secondary address是主链结点的子链结点中的IP,这一点一定注意,概念是不能混淆的。前面说的只是吊链中主链的作用,那么子链呢?其实想象一下也很简单,比 如一台机器上运行着一个代理服务器或者负载均衡服务,代理服务器或者负载均衡服务和主服务器要监听相同的端口,那么就可以用secondary address来解决了,只要需要在同一网段监听同一个端口的应用都是吊链中子链存在的原因,因此可以说,主链对外部或者说对下面链路层虚拟了多块网卡, 而子链向上层虚拟了多台机器,配置了吊链结构的linux主机如果说只有一块网卡,那么外部会认为它有多块网卡,对于内部,应用层会认为彼此在不同的主机 上,这就是效果。 除了上面大体的介绍之外,还有很多细节,吊链在主链上是没有主次的,子链除了第一个节点其它节点也不分主次,都是平行的关系,但是子链中的第一个节点总是 链接在主链中,它们携带的地址就是primary地址,它们下面隶属的子链携带的地址就是这个primary地址的secondary地址,如此看来,一 旦主链上一个节点被删除了,那么它的子链也将不复存在,所谓皮之不存毛将焉附。但是这种策略总是显得不是那么优美,因为父亲犯错,儿子也要受连累,这在现 代社会早就不时行了,那么就需要改变机制了,因此linux中特意有了一个选项,就是当一个primary地址被删除时,如果它有secondary地址 的话,那么它的第一个secondary地址(长子)继承被删除的primary地址的位置成为primary地址,这样就显得很合理了,要不然在删除 primary地址的时候,如果有程序用secondary地址,那么要么延迟删除,要么程序崩溃,采用自动提升策略的话就不会出现问题。 至于说IP aliases,那是以前版本有的了,就是一个实现问题,解决的问题和现在的secondary IP机制一样,它主要就是在物理网卡名字后面加上后缀从而成为虚拟网络接口,本质上和secondary IP机制没有区别,区别就是IP aliases显得不是那么直观,而secondary IP却是真正让应用看到了一个网卡的多个地址,比如你要是用IP aliases的话,有的时候你总是会问eth0:0是什么?我就曾经在内核里面拼命找eth0:0这个网络设备的注册代码,都要疯掉了也没有找到,其实 我并不是很傻,但是我却因为那个该死的名字作出了傻事。 下面就可以看看linux内核的实现代码了,首先弄明白一些数据结构,最重要的就是net_device,其次就是in_device,然后就是in_ifaddr,明白了这三个数据结构,一切就明白了,这是真的。
struct net_device { ... void *ip_ptr; //指向一个in_device结构,这字段从net_device中分离表明一个网卡可以支持多种网络层协议的 ... } struct in_device { struct net_device *dev; //指向它隶属的net_device,也就是网卡 atomic_t refcnt; //引用计数 int dead; struct in_ifaddr *ifa_list; //所有的ip地址链表 ... }; struct in_ifaddr //代表一个ip地址 { struct in_ifaddr *ifa_next; //上面的in_device中的ifa_list字段就是靠这个字段连成链的 struct in_device *ifa_dev; //回指in_device结构 struct rcu_head rcu_head; u32 ifa_local; //ip地址 u32 ifa_address; u32 ifa_mask; //掩码 u32 ifa_broadcast; //广播地址 u32 ifa_anycast; unsigned char ifa_scope; unsigned char ifa_flags; //只有IFA_F_SECONDARY标志,因为除了这个就是primary地址了 unsigned char ifa_prefixlen; char ifa_label[IFNAMSIZ]; //名字,在ip aliases时代,它就可能是ethx:y的形式,在secondary ip时代,它统一就是ethx };注 意,上面的结构并没有将linux网卡的ip地址结构表示为吊链结构,所谓的吊链结构只是逻辑上的,在数据结构上,一个网卡所有的ip地址全部都在 ifa_list中被链接成一个线性的链表,至于是primary地址还是secondary地址就看in_ifaddr的ifa_flags字段了。每 当有新的地址被设置的时候,inet_insert_ifa总是被调用,linux为何没有在代码上将ip地址表示为吊链结构呢?我也不知道,个人感觉一 个net_device带有一个primary ip链表,然后每个primary ip节点带有一个secondary ip链表,这样会更好一些的,我觉得inet_insert_ifa实现的十分拙劣。添加地址可以通过两个用户空间程序搞定,一个是ifconfig,另 一个是ip addr add,ifconfig是基于ioctl进行地址添加的,而ip程序是基于netlink进行地址添加的,不管哪一种方式都可以达到目的,现在就可以看 看另一个问题了:为何用ip addr add添加的ip地址用ifconfig看不到,而ifconfig设置的地址ip addr show却是可以看到。这个问题通过看代码一眼就可以明白,在ifconfig获得ip地址的时候,代码:
for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL; ifap = &ifa->ifa_next) { if (!strcmp(ifr.ifr_name, ifa->ifa_label) && sin_orig.sin_addr.s_addr == ifa->ifa_address) { break; } }取 的是这个被找到的ifa的ip地址,而我们知道,所有的ifa链接成一个线性链表,那么找到了第一个就不会再往后走了,因此只能得到一个结果,就是链表最 前面的那个,而ip add show就不同了,具体在函数inet_mp_ifaddr中实现,该函数遍历所有的ifa,并且传到用户空间缓冲区。这里可以做一个实验:首先用 ip addr add添加几个不在同一个网段的primary ip地址,然后再ifconfig一个和前面的ip都不在一个网段的ip,然后可以用ifconfig查看一下,发现不是刚刚用ifconfig设置进去 的那个ip,而是用ip addr add添加进去的,这就说明ifconfig永远都是取的ifa链表最前面的那一个,还有一点要注意,就是如果你用ip addr add添加了很多的secondary ip地址,那么恰好你用ifconfig设置的ip地址和那些secondary ip在一个网段,那么所有的secondary ip都将被删除,这些都是sencondary ip的规范决定的,而且在代码中也有体现。另外还要注意,路由表的表项都是基于primary ip的,因为所有的操作都是以primary ip为主的,比如在添加路由的时候:
void fib_add_ifaddr(struct in_ifaddr *ifa) { struct in_device *in_dev = ifa->ifa_dev; struct net_device *dev = in_dev->dev; struct in_ifaddr *prim = ifa; ... if (ifa->ifa_flags&IFA_F_SECONDARY) { //如果ifa是个sencondary地址,那么就找到它隶属的primary地址后然后以这个primary为主进行设置 prim = inet_ifa_byprefix(in_dev, prefix, mask); if (prim == NULL) { printk(KERN_DEBUG "fib_add_ifaddr: bug: prim == NULL/n"); return; } } fib_magic(RTM_NEWROUTE, RTN_LOCAL, addr, 32, prim); //添加进路由表 ... }到 此为止我们知道了不少东西,最重要的就是linux中网卡ip地址的吊链结构以及这么设计的好处,另外就是设置ip地址的方式有ioctl和 netlink。其实网卡拥有多个ip并不会带来什么冲突,本质上ip和网卡没有什么关系,它们唯一的关系就是靠网络分层模型联系在一起的,细节上就是靠 路由联系在一起的,比如我添加路由的时候指定了一个目的地址和下一跳ip地址以及一个网卡出口,那么内核会根据提供的目的地址将路由插在合式的位置,然后 将nh的网络设备设置为你提供的网卡出口,等到传输数据的时候就会查找路由从而找到出口,就是这么简单,你自己手动设置的路由可以随意设置,即使完全错误 内核也会将之加入路由表的,还有一种路由是内核自动生成的,就是在网卡刚刚up的时候,这时通过网卡的net_device找到其in_device然后 找到其ip地址,这样的路由称为链路路由。 通过secondary IP机制,你可以认为你的机器有很多网卡,对于应用,监听同一端口的应用会认为它们在局域网中不同的机器上,你可以随意使用这些ip地址而不会发生混乱,路由和底层的arp会处理好这一切,当然前提是你将路由设置对。 附: 用户空间有ifup/ifdown,/sbin/ip,ifconfig,还有netplugd守护进程,这些有何关系吗?这中间ip程序是最基本的,没 有任何策略,策略就是参数指定,要么就是别的程序调用它,而netplugd就是一个监控守护进程,通过netlink监控网卡状态,然后根据不同的监控 结果调用/etc/netplug.d/netplug脚本,进而可能调用ifup/ifdown脚本,而后者就是脚本,其中会调用ifup-eth脚 本,最终整理好参数后调用ip程序(典型的就是:ip link set eth0 up/down),当然ip程序完全可以自己调用,比如ip addr add以及ip route add等等,而ifconfig没有那么绕圈子,就是通过ioctl进行设置,可以通过strace来观察。这其中奥妙大了去了,说白了就是策略和机制分 离,另外还体现出linux中的很多功能都是很小的程序组合而成的。
Linux的ip地址的吊链结构以及ip地址的寻址特性(详见《关于IP网段间互访的问题—路由是根本》)充分说明了linux的协议栈实现多么的完美,完全符合分层和封装模型,使得下层的逻辑和上层的逻辑完全解除耦合,也就是说ip层完全不依赖链路层以及物理层的物理布局,最后记住,ip层事情比如寻址路由只由ip层实现,之所有有链路层发现的路由,完全是为了方便。
❷ 从ip addr add和ifconfig的区别看linux网卡ip地址的结构
如果你非常理解网络协议的原理以及网络的分层架构那么我想你就不会有这个问题,实际上,每一个网卡设备都有一个mac地址,但是却可 以有多个网络层地址,比如IP地址,然而这个事实无法很好地像用户提供操作接口,所以就引出了ip别名(IP aliases)和辅助ip(secondary IP addresses)的概念。其实很容易理解这个事实,按照分层的思想,下层总是为上层服务,也就是为上层提供舞台,上层利用下层的服务,而不必让下层知 道自己的情况,如果一个拥有合理mac地址的网卡没有配置网络层地址(比如IP地址)这件事合理的话,那么为这个设备配置多个IP地址也是合理的,正好像 一个ip可以对应多个应用层端口一样,也就是说,下层对上层总是一对多的关系,在分层架构中这种关系是合理的。下面我们就看一下linux的网卡的ip地 址结构。刚才说了在linux中,一个网卡可以有多个IP,那么这多个ip有什么关系呢?其实这些ip组成了一个吊链结构,所谓吊链结构就是一些节点链接 成一条链,然后每个节点带有自己的一条链
每个节点代表的ip地址标识一个网段,这个节点的ip就是这个网段的 Primary地址,它下面所带的ip就是这个网段的Secondary地址,也就是说一个网卡可以带有各个节点所带链表长度之和个ip地址,而且这些 ip不是线形的,而是上述的吊链结构。我们看一下这么做有什么好处。玩过Cisco路由器的朋友可能都知道有个Secondary IP的概念,这个特性可以创建逻辑子网,也就是说在一个物理网口上连接两个子网,这咋看起来好像不可思议,其实很简单,比如这个网口接到一台交换机上,如 果这个网口没有配置Secondary IP的话,那么这台交换机只能连接一个网段的主机,比如192.168.1.1/24,但是,如果它配置了Secondary IP,那么就可以连接两个网段的主机,比如192.168.1.1/24和10.0.0.1/24,道理就是这么简单,但是却很有用,该机制可以被路由汇 总策略所使用。注意上面这个例子中的Secondary IP不是这里说的linux的Secondary address,在linux中恰恰相反,只要一个网卡上配置的ip不是一个网段的,那么都是Primary IP,就是吊链结构中上面的那条主链中的IP,linux中的Secondary address是主链结点的子链结点中的IP,这一点一定注意,概念是不能混淆的。前面说的只是吊链中主链的作用,那么子链呢?其实想象一下也很简单,比 如一台机器上运行着一个代理服务器或者负载均衡服务,代理服务器或者负载均衡服务和主服务器要监听相同的端口,那么就可以用secondary address来解决了,只要需要在同一网段监听同一个端口的应用都是吊链中子链存在的原因,因此可以说,主链对外部或者说对下面链路层虚拟了多块网卡, 而子链向上层虚拟了多台机器,配置了吊链结构的linux主机如果说只有一块网卡,那么外部会认为它有多块网卡,对于内部,应用层会认为彼此在不同的主机 上,这就是效果。
除了上面大体的介绍之外,还有很多细节,吊链在主链上是没有主次的,子链除了第一个节点其它节点也不分主次,都是平行的关系,但是子链中的第一个节点总是 链接在主链中,它们携带的地址就是primary地址,它们下面隶属的子链携带的地址就是这个primary地址的secondary地址,如此看来,一 旦主链上一个节点被删除了,那么它的子链也将不复存在,所谓皮之不存毛将焉附。但是这种策略总是显得不是那么优美,因为父亲犯错,儿子也要受连累,这在现 代社会早就不时行了,那么就需要改变机制了,因此linux中特意有了一个选项,就是当一个primary地址被删除时,如果它有secondary地址 的话,那么它的第一个secondary地址(长子)继承被删除的primary地址的位置成为primary地址,这样就显得很合理了,要不然在删除 primary地址的时候,如果有程序用secondary地址,那么要么延迟删除,要么程序崩溃,采用自动提升策略的话就不会出现问题。
至于说IP aliases,那是以前版本有的了,就是一个实现问题,解决的问题和现在的secondary IP机制一样,它主要就是在物理网卡名字后面加上后缀从而成为虚拟网络接口,本质上和secondary IP机制没有区别,区别就是IP aliases显得不是那么直观,而secondary IP却是真正让应用看到了一个网卡的多个地址,比如你要是用IP aliases的话,有的时候你总是会问eth0:0是什么?我就曾经在内核里面拼命找eth0:0这个网络设备的注册代码,都要疯掉了也没有找到,其实 我并不是很傻,但是我却因为那个该死的名字作出了傻事。
下面就可以看看linux内核的实现代码了,首先弄明白一些数据结构,最重要的就是net_device,其次就是in_device,然后就是in_ifaddr,明白了这三个数据结构,一切就明白了,这是真的。
structnet_device
{
...
void*ip_ptr;//指向一个in_device结构,这字段从net_device中分离表明一个网卡可以支持多种网络层协议的
...
}
structin_device
{
structnet_device*dev;//指向它隶属的net_device,也就是网卡
atomic_trefcnt;//引用计数
intdead;
structin_ifaddr*ifa_list;//所有的ip地址链表
...
};
structin_ifaddr//代表一个ip地址
{
structin_ifaddr*ifa_next;//上面的in_device中的ifa_list字段就是靠这个字段连成链的
structin_device*ifa_dev;//回指in_device结构
structrcu_headrcu_head;
u32ifa_local;//ip地址
u32ifa_address;
u32ifa_mask;//掩码
u32ifa_broadcast;//广播地址
u32ifa_anycast;
unsignedcharifa_scope;
unsignedcharifa_flags;//只有IFA_F_SECONDARY标志,因为除了这个就是primary地址了
unsignedcharifa_prefixlen;
charifa_label[IFNAMSIZ];//名字,在ipaliases时代,它就可能是ethx:y的形式,在secondaryip时代,它统一就是ethx
};
注 意,上面的结构并没有将linux网卡的ip地址结构表示为吊链结构,所谓的吊链结构只是逻辑上的,在数据结构上,一个网卡所有的ip地址全部都在 ifa_list中被链接成一个线性的链表,至于是primary地址还是secondary地址就看in_ifaddr的ifa_flags字段了。每 当有新的地址被设置的时候,inet_insert_ifa总是被调用,linux为何没有在代码上将ip地址表示为吊链结构呢?我也不知道,个人感觉一 个net_device带有一个primary ip链表,然后每个primary ip节点带有一个secondary ip链表,这样会更好一些的,我觉得inet_insert_ifa实现的十分拙劣。添加地址可以通过两个用户空间程序搞定,一个是ifconfig,另 一个是ip addr add,ifconfig是基于ioctl进行地址添加的,而ip程序是基于netlink进行地址添加的,不管哪一种方式都可以达到目的,现在就可以看 看另一个问题了:为何用ip addr add添加的ip地址用ifconfig看不到,而ifconfig设置的地址ip addr show却是可以看到。这个问题通过看代码一眼就可以明白,在ifconfig获得ip地址的时候,代码:
for(ifap=&in_dev->ifa_list;(ifa=*ifap)!=NULL;ifap=&ifa->ifa_next)
{
if(!strcmp(ifr.ifr_name,ifa->ifa_label)&&sin_orig.sin_addr.s_addr==ifa->ifa_address)
{
break;
}
}
取 的是这个被找到的ifa的ip地址,而我们知道,所有的ifa链接成一个线性链表,那么找到了第一个就不会再往后走了,因此只能得到一个结果,就是链表最 前面的那个,而ip add show就不同了,具体在函数inet_mp_ifaddr中实现,该函数遍历所有的ifa,并且传到用户空间缓冲区。这里可以做一个实验:首先用 ip addr add添加几个不在同一个网段的primary ip地址,然后再ifconfig一个和前面的ip都不在一个网段的ip,然后可以用ifconfig查看一下,发现不是刚刚用ifconfig设置进去 的那个ip,而是用ip addr add添加进去的,这就说明ifconfig永远都是取的ifa链表最前面的那一个,还有一点要注意,就是如果你用ip addr add添加了很多的secondary ip地址,那么恰好你用ifconfig设置的ip地址和那些secondary ip在一个网段,那么所有的secondary ip都将被删除,这些都是sencondary ip的规范决定的,而且在代码中也有体现。另外还要注意,路由表的表项都是基于primary ip的,因为所有的操作都是以primary ip为主的,比如在添加路由的时候:
voidfib_add_ifaddr(structin_ifaddr*ifa)
{
structin_device*in_dev=ifa->ifa_dev;
structnet_device*dev=in_dev->dev;
structin_ifaddr*prim=ifa;
...
if(ifa->ifa_flags&IFA_F_SECONDARY){//如果ifa是个sencondary地址,那么就找到它隶属的primary地址后然后以这个primary为主进行设置
prim=inet_ifa_byprefix(in_dev,prefix,mask);
if(prim==NULL){
printk(KERN_DEBUG"fib_add_ifaddr:bug:prim==NULL/n");
return;
}
}
fib_magic(RTM_NEWROUTE,RTN_LOCAL,addr,32,prim);//添加进路由表
...
}
到 此为止我们知道了不少东西,最重要的就是linux中网卡ip地址的吊链结构以及这么设计的好处,另外就是设置ip地址的方式有ioctl和 netlink。其实网卡拥有多个ip并不会带来什么冲突,本质上ip和网卡没有什么关系,它们唯一的关系就是靠网络分层模型联系在一起的,细节上就是靠 路由联系在一起的,比如我添加路由的时候指定了一个目的地址和下一跳ip地址以及一个网卡出口,那么内核会根据提供的目的地址将路由插在合式的位置,然后 将nh的网络设备设置为你提供的网卡出口,等到传输数据的时候就会查找路由从而找到出口,就是这么简单,你自己手动设置的路由可以随意设置,即使完全错误 内核也会将之加入路由表的,还有一种路由是内核自动生成的,就是在网卡刚刚up的时候,这时通过网卡的net_device找到其in_device然后 找到其ip地址,这样的路由称为链路路由。
通过secondary IP机制,你可以认为你的机器有很多网卡,对于应用,监听同一端口的应用会认为它们在局域网中不同的机器上,你可以随意使用这些ip地址而不会发生混乱,路由和底层的arp会处理好这一切,当然前提是你将路由设置对。
附: 用户空间有ifup/ifdown,/sbin/ip,ifconfig,还有netplugd守护进程,这些有何关系吗?这中间ip程序是最基本的,没 有任何策略,策略就是参数指定,要么就是别的程序调用它,而netplugd就是一个监控守护进程,通过netlink监控网卡状态,然后根据不同的监控 结果调用/etc/netplug.d/netplug脚本,进而可能调用ifup/ifdown脚本,而后者就是脚本,其中会调用ifup-eth脚 本,最终整理好参数后调用ip程序(典型的就是:ip link set eth0 up/down),当然ip程序完全可以自己调用,比如ip addr add以及ip route add等等,而ifconfig没有那么绕圈子,就是通过ioctl进行设置,可以通过strace来观察。这其中奥妙大了去了,说白了就是策略和机制分 离,另外还体现出linux中的很多功能都是很小的程序组合而成的。
Linux的ip地址的吊链结构以及ip地址的寻址特性(详见《关于IP网段间互访的问题—路由是根本》)充分说明了linux的协议栈实现多么的完美,完全符合分层和封装模型,使得下层的逻辑和上层的逻辑完全解除耦合,也就是说ip层完全不依赖链路层以及物理层的物理布局,最后记住,ip层事情比如寻址路由只由ip层实现,之所有有链路层发现的路由,完全是为了方便。
❸ 图说智慧型手表风流史,来看 Apple Watch 的前辈们
虎嗅网:罗马不是一天建成的,智能手表也不是最近才发明的。
关于AppleWatch的讨论正酣,一定有越来越多的厂商和创业团队也在打智能手表的主意。
回顾下智能手表的发展历程,正是时候。
本文转自网易科技,原标题为《买买买!智能手表的风流史》,虎嗅编辑后发布。
苹果公司在最近召开的春季发布会上公布了AppleWatch的细节信息以及具体的上市时间,与iPhone和iPad一样,尽管AppleWatch是史上最受关注的新款智能手表,但苹果却并不是首家推出此类产品的厂商,而已经推出多款智能手表的三星和索尼也不是。实际上,首款智能手表要追溯到1927年,同时在上世纪80年代和90年代已经出现过一次较大规模的热潮。
这里结合外媒的报导,盘点了智能手表发展史上比较有代表性的19款重要产品,正是有了这些产品的存在,才让AppleWatch的成功成为一种可能。
(1)PlusFour腕上路线指引器
发布时间:1927年
产品简介:早在上世纪的20年代,GPS还没有出现,但这款最早的“智能手表”仍然能够帮助佩戴者识别从A到B的具体路线,当然,其所采用的不过时间一个插槽式地图盒放置在手腕上,通过旋钮来手动调节要显示的内容。尽管这款无法显示时间的“手表”看起来非常简单,但它的功能也确实非常有针对性,同时用户完全不用考虑它的电池续航时间。
(2)Pulsar电子手表
发布时间:1972年
产品简介:知名美国手表品牌汉密尔顿(Hamilton)在1972年(一说1971年)推出了世界上的首款数字式电子手表Pulsar,这款手表的表面镀了一层18K黄金。Pulsar配备了一个LED屏幕,同时在查看时间时需要按下机身上的按钮。这款在当时颇为先进的电子手表要价2100美元,基本上也算是价格不菲了。
(3)精工电视手表(TVWatch)
发布时间:1982年
产品简介:这款手表曾经在第13部007电影《八爪女》(Octopussy)中被詹姆斯·邦德佩戴,而它“智能”的地方在于通过连接一个适配器和一个接收盒,可以同时在屏幕上方显示时间,而在下方显示颗粒感比较强的电视图像,所以这款在当时要价500英镑的手表实际上更像是一款能够戴在手腕上的显示器。
(4)精工Data-2000智能手表
发布时间:1983年
产品简介:这款手表能够存储备忘录(尽管只有两条)和日历,同时还可以充当计算器使用,当然此时你需要使用配套的键盘才能实现。日本手表厂商精工在上世纪80年代推出了多款智能手表,除了Data-2000之外,同年精工还推出了UC-2000、RC-1000、MemoDiary和UC-3000等智能手表产品。
(5)Sinclair腕上收音机
发布时间:1985年
产品简介:英国的Sinclair公司曾经凭借一款名为ZXSpectrum的8位个人电脑获得巨大成功,随后该公司联合美国手表厂商天美时(Timex)研发了一款比较奇葩的腕上收音机,这款产品由液晶手表、压电扬声器和FM调谐器三个独立部分组成,同时还有一个内置在卡扣上的电池仓。由于当时恰逢Sinclair公司遭遇财务危机,这款手表并未走过原型期就被公司叫停,当时仅生产了11000块。
(6)精工MessageWatch智能手表
发布时间:1995年
产品简介:这款手表已经颇有智能手表的范儿了,不仅能够显示来电者ID(通过FM调频信号),同时还支持体育比赛、股票价格和天气预报等信息更新,这些功能与如今的GoogleNow比较相似,只不过它出现在20年前,同时其屏幕也不过是一块非常普通的单色屏幕。
(7)百年灵紧急求救腕表(EmergencyWatch)
发布时间:1995年
产品简介:瑞士手表品牌百年灵(Breitling)的这款腕表可以在90海里范围内发送紧急求救信号,让救援人员确定遇险对象的所在位置,该手表曾在2003年帮助两名英国飞行员顺利脱险(其所驾驶的直升机在南极区域坠毁)。2013年,百年灵对该产品系列进行了更新,发布了EmergencyII,售价9000英镑。
(8)Linux腕表
发布时间:1998年
产品简介:“可穿戴计算之父”史蒂夫·曼恩(SteveMann)在1998年打造了首款由Linux驱动的智能手表产品,IBM在两年后生产出了这款手表的原型机。“这款手表被设计用来与电脑、手机和其它无线设备进行无线通讯,同时,该手表还具备查看电子邮件和直接接收寻呼机类信息的功能,”当年的材料这样写道,“未来该手表还将配备高清屏幕,同时支持应用程序的安装和运行,此外还能充当互联网服务的接入窗口,包括最新的天气信息、交通状况、股市变化、体育比赛结果等等。”看到这里,或许你就知道曼恩为何被成为是“可穿戴计算之父”了。
(9)FossilPalmPilot智能手表
发布时间:2002年
产品简介:美国时尚生活品牌Fossil最近透露称要重新进军可穿戴市场,计划联合英特尔推出智能手表产品。该公司曾在12年前推出过一款名为PalmPilot的智能手表,该手表曾在2002年荣获当年的Cox展会“最佳产品”奖项,PalmPilot配备了分辨率为160*160的屏幕和2MB的存储空间,同时还内置了多款Palm应用,包括地址薄、记事本、待办事项和计算器,此外需要指出的是,这款手表的操作系统采用了可视化风格,这也是该产品的一大亮点。
(10)微软SPOT设备
发布时间:2003年
产品简介:最近有传言称微软目前正在研发一款全新的可穿戴设备,但在十多年前,微软已经就已经在联合西铁城、天美时、Fossil和松拓等手表厂商联合研发了采用“智能个人对象技术”(SmartPersonalObjectTechnology,简称SPOT”的设备,不过微软在2008年叫停了该项目,而其所提出的每年59美元的服务更新订阅费也并未真正获得消费者的认可。
(11)佳明ForerunnerGPS腕表
发布时间:2003年
产品简介:美国GPS厂商佳明在GPS运动腕表领域一直位居前列,该公司早在10多年前就推出了手表产品,初代Forerunner腕表虽然看起来相当笨拙,但是却已经具备了测量速度、距离、步幅和热量消耗等功能,这也为以后的Forerunner系列腕表的强大功能打下了坚实基础。此外,这款产品的电量由两节AAA电池供应,可以持续使用14个小时的时间。
(12)Nike+Fuelband运动手环
发布时间:2012年
产品简介:毫不夸张地说,Nike+Fuelband运动手环是一款取得巨大成功的可穿戴产品,它可以追踪佩戴者一整天的活动情况,同时还支持蓝牙同步功能。2013年耐克还对该产品进行了更新,加入了环境光功能,方便佩戴者的光线较暗的情况下查看相应地信息。不过可惜的是,耐克在2014年年初解散了Fuelband硬件团队,转而关注软件应用服务。
(13)索尼SmartWatch智能手表
发布时间:2012年
产品简介:初代索尼SmartWatch智能手表实际上是Xperia智能手机的配套设备,该手表运行一个变种的Android,配备了1.3英寸的OLED屏幕,这款产品在当年深受各大科技媒体的喜爱,尽管它经常出现毫无征兆的系统奔溃情况。索尼随后在2013年推出的SmartWatch2获得了巨大成功,而其第三代产品、搭载AndroidWear的SmartWatch3已经在IFA2014上亮相。
(14)Pebble智能手表
发布时间:2013年
产品简介:到目前为止,Pebble智能手表仍然是众筹平台Kickstarter上最为成功的项目,这款产品重新将智能手表的功能拉回到正确的发展轨道上来,把通知推送功能放在最为重要的位置上,除了该功能之外,Pebble还能够充当智能手机或GoPro运动相机的远程控制器,目前Pebble应用商店里有超过1000款应用,基本上能够满足大部分用户的需求。
(15)三星GalaxyGear智能手表
发布时间:2013年
产品简介:在IFA2013上亮相的GalaxyGear是三星进军智能手表市场的开山之作,如今三星已经推出了6款智能手表产品,很显然,三星非常希望在这一群雄纷争的领域中获得成功,但就目前情况来看,三星要想获得像苹果粉丝对AppleWatch那样的追捧,还有很长的一段路要走。
(16)三星GearFit智能手环
发布时间:2014年产品简介:如果说GalaxyGear为三星打开了可穿戴设备市场,那么GearFit则是一款让三星赢得满堂彩的手环产品,这款在MWC2014发布的产品一经亮相就凭借其独特的OLED曲面屏幕成为展会的亮点之一。
(17)Moto360智能手表
发布时间:2014年产品简介:2014年3月,谷歌在I/O大会上发布了可穿戴操作系统AndroidWear,在当时发布的三款AndroidWear设备中,Moto360无疑是关注度最高的一款,这款配备圆形表盘、售价199英镑的智能手表到现在为止还被认为是AppleWatch的主要竞争对手之一。
(18)三星GearS智能手表
发布时间:2014年产品简介:三星GearS内置了3G模块,所以其可以在不与智能手机配对的情况下独立使用,这款产品反映出三星对智能手表市场的认知已经比较深厚,除了内置3G模块之外,其所采用的2英寸的SuperAMOLED曲面屏幕、高达360*480的分辨率都让人眼前一亮。
(19)AppleWatch智能手表
上市时间:2015年
产品简介:2014年9月,苹果在新款iPhone的发布会上推出了传闻已久的智能手表产品AppleWatch,关于这款产品的设计、配置和售价已无需赘述,这款定于4月24日正式开售的智能手表自诞生之日起就备受关注,所以不管其未来能否获得成功,都将会是智能手表发展史上浓墨重彩的一笔。
你或许会喜欢
跟回合制游戏说掰~掰~不再无聊的手游在这里
❹ linux下里面如何获取网卡的实时网速
#include <time.h>
#include "tspeed.h"
int main ()
{
struct if_speed ndev;
int ret = 0;
bzero(&ndev,sizeof(ndev));
sprintf(ndev.ifs_name,"eth0");
ndev.ifs_us = 100000;
printf("Get %s Speed",ndev.ifs_name);
#if 1
ret = get_if_speed(&ndev);
if(ret < 0)
printf("[Fail]\n");
else
printf("[OK]\n");
float ispeed ,ospeed;
while(1){
time_t *timep = malloc(sizeof(*timep));
time(timep);
char *s = ctime(timep);
ispeed = ndev.ifs_ispeed * 1.0/(ndev.ifs_us/1000 * 0.001);
ospeed = ndev.ifs_ospeed * 1.0/(ndev.ifs_us/1000 * 0.001);
#if 0
printf("%s: Up Speed: %fMB/s || Down Speed: %fMB/s\r",
ndev.ifs_name,ispeed/(1024.0*1024.0),ospeed/(1024.0*1024.0));
#endif
sleep(3);
#if 1
printf("*****************************************************\n");
printf("*****************************************\n");
printf("***************************\n");
printf("*************\n");
printf("Time is %s || Down Speed: %fKB/s\n",s,ospeed/(1024.0));
#endif
get_if_speed(&ndev);
}
#endif
return 0;
} /* ----- End of main() ----- */
----------------------------------------------------------------------------
#include "tspeed.h"
int get_if_dbytes(struct if_info* ndev)
{
assert(ndev);
struct ifaddrs *ifa_list = NULL;
struct ifaddrs *ifa = NULL;
struct if_data *ifd = NULL;
int ret = 0;
ret = getifaddrs(&ifa_list);
if(ret < 0) {
perror("Get Interface Address Fail:");
goto end;
}
for(ifa=ifa_list; ifa; ifa=ifa->ifa_next){
if(!(ifa->ifa_flags & IFF_UP) && !(ifa->ifa_flags & IFF_RUNNING))
continue;
if(ifa->ifa_data == 0)
continue;
ret = strcmp(ifa->ifa_name,ndev->ifi_name);
if(ret == 0){
ifd = (struct if_data *)ifa->ifa_data;
ndev->ifi_ibytes = ifd->ifi_ibytes;
ndev->ifi_obytes = ifd->ifi_obytes;
break;
}
}
freeifaddrs(ifa_list);
end:
return (ret ? -1 : 0);
}
int get_if_speed(struct if_speed *ndev)
{
assert(ndev);
struct if_info *p1=NULL,*p2=NULL;
p1 = (struct if_info *)malloc(sizeof(struct if_info));
p2 = (struct if_info *)malloc(sizeof(struct if_info));
bzero(p1,sizeof(struct if_info));
bzero(p2,sizeof(struct if_info));
strncpy(p1->ifi_name,ndev->ifs_name,strlen(ndev->ifs_name));
strncpy(p2->ifi_name,ndev->ifs_name,strlen(ndev->ifs_name));
int ret = 0;
ret = get_if_dbytes(p1);
if(ret < 0) goto end;
usleep(ndev->ifs_us);
ret = get_if_dbytes(p2);
if(ret < 0) goto end;
ndev->ifs_ispeed = p2->ifi_ibytes - p1->ifi_ibytes;
ndev->ifs_ospeed = p2->ifi_obytes - p1->ifi_obytes;
end:
free(p1);
free(p2);
return 0;
}
------------------------------------------
#ifndef __TSPEED_H__
#define __TSPEED_H__
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <error.h>
#include <ifaddrs.h>
#include <net/if.h> /* for ifconf */
#include <linux/sockios.h> /* for net status mask */
#include <netinet/in.h> /* for sockaddr_in */
#include <sys/socket.h>
#include <sys/ioctl.h>
/* For "open" function */
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
struct if_data
{
/* generic interface information */
u_long ifi_opackets; /* packets sent on interface */
u_long ifi_ipackets; /* packets received on interface */
u_long ifi_obytes; /* total number of octets sent */
u_long ifi_ibytes; /* total number of octets received */
};
struct if_info
{
char ifi_name[16];
unsigned long ifi_ibytes;
unsigned long ifi_obytes;
};
struct if_speed
{
char ifs_name[16];
unsigned long ifs_ispeed;
unsigned long ifs_ospeed;
unsigned long ifs_us;
};
int get_if_dbytes(struct if_info *ndev);
int get_if_speed(struct if_speed *ndev);
#endif
------------------------
纯手打 代码都给你了
❺ sublime 列编辑的功能求助
Preferences.sublime-settings文件://Whileyoucaneditthisfile,it’sbesttoputyourchangesin//逗User/Preferences.sublime-settings地,.////,for//example,inPackages/python/Python.sublime-settingsforpythonfiles.{////主题文件的路径逗color_scheme地:逗Packages/ColorScheme–Default/Monokai.tmTheme地,//Notethatthefont_faceandfont_sizeareoverridenintheplatform//specificsettingsfile,forexample,逗Preferences(Linux).sublime-settings地.//Becauseofthis,:youmustsetthem//inyourUserFilePreferences.//设置字体和大小,必须在Settings-User里重写,这里设置没有任何效果逗font_face地:逗Consolas地,逗font_size地:12,//Validoptionsare逗no_bold地,逗no_italic地,逗no_antialias地,逗gray_antialias地,//逗subpixel_antialias地and逗no_round地(OSXonly)//字体选项:no_bold不显示粗体字,no_italic不显示斜体字,no_antialias和no_antialias关闭反锯齿//subpixel_antialias和no_round是OSX系统独有的逗font_options地:[],////在文字上双击会全选当前的内容,如果里面出现以下字符,就会被截断逗word_separators地:逗./\\()\地‘-:,.;~!@#$%^&*|+=[]{}`~?地,////是否显示行号逗line_numbers地:true,////是否显示行号边栏逗gutter地:true,////行号边栏和文字的间距逗margin地:4,////是否显示代码折叠按钮逗fold_buttons地:true,////不管鼠标在不在行号边栏,代码折叠按钮一直显示逗fade_fold_buttons地:true,////列显示垂直标尺,在中括号里填入数字,宽度按字符计算逗rulers地:[],////是否打开拼写检查逗spell_check地:false,////Tab键制表符宽度逗tab_size地:4,////设为true时,缩进和遇到Tab键时使用空格替代逗translate_tabs_to_spaces地:false,//Iftranslate_tabs_to_spacesistrue,use_tab_stopswillmaketaband//backspaceinsert/deleteuptothenexttabstop//translate_tabs_to_spaces设置为true,Tab和Backspace的删除/插入作用于制表符宽度//否则作用于单个空格逗use_tab_stops地:true,//.spacesonload//false时禁止在载入的时候检测制表符和空格逗detect_indentation地:true,////按回车时,自动与制表位对齐逗auto_indent地:true,//Makesautoindentalittlesmarter,e.g.,byindentingthenextline//afteranifstatementinC.Requiresauto_indenttobeenabled.//针对c语言的逗smart_indent地:false,//.Requires//auto_indenttobeenabled.//需要启用auto_indent,第一次打开括号缩进时插入空格看(没测试出来效果…)逗indent_to_bracket地:true,//Trimswhitespaceaddedbyauto_//line.//显示对齐的白线是否根据回车、tab等操作自动填补逗trim_automatic_white_space地:true,//.//Maybesettotrue,false,or逗auto地,whereitwillbedisabledfor//sourcecode,andotherwiseenabled.//是否自动换行,如果选auto,需要加双引号逗word_wrap地:false,////windowwidth//设置窗口内文字区域的宽度逗wrap_width地:0,////level//防止被缩进到同一级的字换行逗indent_subsequent_lines地:true,////如果没有定义过,则文件居中显示(比如新建的文件)逗draw_centered地:false,//Controlsautopairingofquotes,bracketsetc//自动匹配引号,括号等逗auto_match_enabled地:true,//Wordlisttouseforspellchecking//拼写检查的单词列表路径逗dictionary地:逗Packages/Language–English/en_US.dic地,//.//逗minimapBorder地keyin//thecolorscheme//代码地图的可视区域部分是否加上边框,边框的颜色可在配色方案上加入minimapBorder键逗draw_minimap_border地:false,//Ifenabled,//突出显示当前光标所在的行逗highlight_line地:false,//Validvaluesare逗smooth地,逗phase地,逗blink地,逗wide地and逗solid地.//设置光标闪动方式逗caret_style地:逗smooth地,////是否特殊显示当前光标所在的括号、代码头尾闭合标记逗match_brackets地:true,//Settofalseifyou’//nexttoone//设为false时,只有光标在括号或头尾闭合标记的两端时,match_brackets才生效逗match_brackets_content地:true,//.Thisonlytakeseffectif//match_bracketsistrue//是否突出显示圆括号,match_brackets为true生效逗match_brackets_square地:false,//.Thisonlytakeseffectif//match_bracketsistrue//是否突出显示大括号,match_brackets为true生效逗match_brackets_braces地:false,//.Thisonlytakeseffectif//match_bracketsistrue//是否突出显示尖括号,match_brackets为true生效逗match_brackets_angle地:false,////html和xml下突出显示光标所在标签的两端,影响HTML、XML、CSS等逗match_tags地:true,////全文突出显示和当前选中字符相同的字符逗match_selection地:true,//,inpixels//设置每一行到顶部,以像素为单位的间距,效果相当于行距逗line_padding_top地:1,//,inpixels//设置每一行到底部,以像素为单位的间距,效果相当于行距逗line_padding_bottom地:1,//.//OnOSX,,so//you’.//设置为false时,滚动到文本的最下方时,没有缓冲区逗scroll_past_end地:true,////orlastline.//OnOSX,,so//you’.//控制向上或向下到第一行或最后一行时发生什么(没明白也没试出来)逗move_to_limit_on_up_down地:false,//Setto逗none地toturnoffdrawingwhitespace,逗selection地todrawonlythe//whitespacewithintheselection,and逗all地todrawallwhitespace//按space或tab时,实际会产生白色的点(一个空格一个点)或白色的横线(tab_size设置的制表符的宽度),选中状态下才能看到//设置为none时,什么情况下都不显示这些点和线//设置为selection时,只显示选中状态下的点和线//设置为all时,则一直显示逗draw_white_space地:逗selection地,//.////thecorresponding.tmThemefile,andspecifyingthecolors逗guide地,//逗activeGuide地and逗stackGuide地//制表位的对齐白线是否显示,颜色可在主题文件里设置(guide,activeGuide,stackGuide)逗draw_indent_guides地:true,//,validoptionsare//逗draw_normal地and逗draw_active地.draw_activewilldrawtheindent//.//制表位的对齐白线,draw_normal为一直显示,draw_active为只显示当前光标所在的代码控制域逗indent_guide_options地:["draw_normal"],////为true时,保存文件时会删除每行结束后多余的空格逗trim_trailing_white_space_on_save地:false,////characterwhensaving//为true时,保存文件时光标会在文件的最后向下换一行逗ensure_newline_at_eof_on_save地:false,////orapplication//切换到其它文件标签或点击其它非本软件区域,文件自动保存逗save_on_focus_lost地:false,//’tbedeterminedautomatically.//ASCII,UTF-8andUTF-.//编码时不能自动检测编码时,将自动检测ASCII,UTF-8和UTF-16逗fallback_encoding地:逗Western(Windows1252)地,//,andfilesopenedwithanundefined//encoding(e.g.,plainasciifiles).Ifafileisopenedwithaspecific//encoding(),thissettingwillbe//ignored,//with.//默认编码格式逗default_encoding地:逗UTF-8″,////包含空字节的文件被打开默认为十六进制逗enable_hexadecimal_encoding地:true,//Determineswhatcharacter(s).//Validvaluesare‘system’(whatevertheOSuses),‘windows’(CRLF)and//‘unix’(LFonly).//每一行结束的时候用什么字符做终止符逗default_line_ending地:逗system地,//Whenenabled,.//Whendisabled,.//Shift+_completionis//enabled.//设置为enabled时,在一个字符串间按Tab将插入一个制表符//设置为true时,按Tab会根据前后环境进行代码自动匹配填补逗tab_completion地:true,//.//代码提示逗auto_complete地:true,//.//代码提示的大小限制逗auto_complete_size_limit地:4194304,//Thedelay,inms,///projectbasis.逗folder_exclude_patterns地:[".svn",".git",".hg","CVS"],逗file_exclude_patterns地:["*.pyc","*.pyo","*.exe","*.dll","*.obj","*.o","*.a","*.lib","*.so","*.dylib","*.ncb","*.sdf","*.suo","*.pdb","*.idb",".DS_Store","*.class","*.psd","*.db"],//,butwon’tbeincludedin//GotoAnythingorFindinFiles逗binary_file_patterns地:["*.jpg","*.jpeg","*.png","*.gif","*.ttf","*.tga","*.dds","*.ico","*.eot","*.pdf","*.swf","*.jar","*.zip"],//Listanypackagestoignorehere.,//.//删除你想要忽略的插件,需要重启逗ignored_packages地:["Vintage"]}
❻ 在Linux中 if [ $ !=0 ] then 的含义
ifthen间的是逻辑表达式,不是赋值表达式。c语言:if(a(i,j)==0)vb6:ifa(i,j)=0thenIfA(i,j)=0ThenA(i,j)=k这句的意思是如果A(i,j)=0,那么给A(i,j)赋值K
❼ C语言如何获取嵌入式linux网卡上的mac地址
全对应的
getmacaddress.c
#include<stdio.h>
#ifdefined(WIN32)||(!defined(__GNUC__)&&!defined(__clang__))
#include<winsock2.h>
#include<iphlpapi.h>
#include<stdlib.h>
#pragmacomment(lib,"IPHLPAPI.lib")
#elifdefined(__linux__)
#include<string.h>//strncpy
#include<sys/ioctl.h>
#include<sys/socket.h>
#include<net/if.h>
#else
//bsd
#include<sys/types.h>//FreeBSDu_int
#include<ifaddrs.h>
#include<net/if.h>
#include<net/if_dl.h>
#include<net/if_types.h>
#endif
voidgetmacaddress(char*mac_address){
#ifdefined(WIN32)||(!defined(__GNUC__)&&!defined(__clang__))
PIP_ADAPTER_INFOpAdapterInfo;
PIP_ADAPTER_INFOpAdapter;
ULONGulOutBufLen=sizeof(IP_ADAPTER_INFO);
unsignedchar*addr;
mac_address[0]=0;
pAdapterInfo=(IP_ADAPTER_INFO*)malloc(sizeof(IP_ADAPTER_INFO));
if(!pAdapterInfo)return;
if(GetAdaptersInfo(pAdapterInfo,&ulOutBufLen)==ERROR_BUFFER_OVERFLOW){
free(pAdapterInfo);
pAdapterInfo=(IP_ADAPTER_INFO*)malloc(ulOutBufLen);
if(!pAdapterInfo)return;
}
if(GetAdaptersInfo(pAdapterInfo,&ulOutBufLen)==NO_ERROR){
pAdapter=pAdapterInfo;
if(pAdapter){
addr=pAdapter->Address;
sprintf(mac_address,"%02x:%02x:%02x:%02x:%02x:%02x",
addr[0],addr[1],addr[2],addr[3],addr[4],addr[5]);
}
}
free(pAdapterInfo);
#elifdefined(__linux__)
mac_address[0]=0;
structifreq*ifr,*ifend;
structifreqifreq;
structifconfifc;
structifreqifs[16];
intfd;
unsignedchar*addr;
fd=socket(AF_INET,SOCK_DGRAM,0);
ifc.ifc_len=sizeof(ifs);
ifc.ifc_req=ifs;
if(ioctl(fd,SIOCGIFCONF,&ifc)<0){close(fd);return;}
ifend=ifs+(ifc.ifc_len/sizeof(structifreq));
for(ifr=ifc.ifc_req;ifr<ifend;ifr++){
if(ifr->ifr_addr.sa_family==AF_INET){
strncpy(ifreq.ifr_name,ifr->ifr_name,sizeof(ifreq.ifr_name));
if(ioctl(fd,SIOCGIFHWADDR,&ifreq)<0)continue;
addr=ifreq.ifr_hwaddr.sa_data;
sprintf(mac_address,"%02x:%02x:%02x:%02x:%02x:%02x",
addr[0],addr[1],addr[2],addr[3],addr[4],addr[5]);
}
}
close(fd);
#else
//bsd
mac_address[0]=0;
structifaddrs*ifa_list,*ifa;
structsockaddr_dl*dl;
unsignedchar*addr;
if(getifaddrs(&ifa_list)<0)return;
for(ifa=ifa_list;ifa;ifa=ifa->ifa_next){
dl=(structsockaddr_dl*)ifa->ifa_addr;
if(dl->sdl_family==AF_LINK&&dl->sdl_type==IFT_ETHER){
addr=(unsignedchar*)LLADDR(dl);
sprintf(mac_address,"%02x:%02x:%02x:%02x:%02x:%02x",
addr[0],addr[1],addr[2],addr[3],addr[4],addr[5]);
return;
}
}
freeifaddrs(ifa_list);
#endif
}
❽ 一台linux可支持多少tcp链接
这个文件是一个综合性的问题。首先就tcp链接来说吧,主要体现在tcp的socket链接数上面,65535 应该是足够用了,但是tcp连接11种状态,不同不同状态有可能有会话保持什么的。这些暂且不说,现在tcp连接的还有Linux下文件的最大打开数量,流量带宽等等。
优化:
1.ulimit -a 查看最大文件打开数量,然后修改
2.减少tcp长连接,或其他状态链接,可以改下会话保持时间,主动自动关闭(不建议),重复使用tcp等。这个是在tcp链接数来进行考虑。
3.增多IP,增多端口,一个IP是这么多,那可以在一台Linux上绑定多个IP来增加链接数。等等
运维是一个大的课题,大家都是在学习中提高的,我的答案不一定正确,大家可以相互指正。更多Linux可以参考《Linux就该这样学》,加油
❾ linux编程获取本机的所有网口名称
struct ifaddrs
{
struct ifaddrs *ifa_next; /* Next item in list */
char *ifa_name; /* Name of interface */
unsigned int ifa_flags; /* Flags from SIOCGIFFLAGS */
struct sockaddr *ifa_addr; /* Address of interface */
struct sockaddr *ifa_netmask; /* Netmask of interface */
union
{
struct sockaddr *ifu_broadaddr; /* Broadcast address of interface */
struct sockaddr *ifu_dstaddr; /* Point-to-point destination address */
} ifa_ifu;
#define ifa_broadaddr ifa_ifu.ifu_broadaddr
#define ifa_dstaddr ifa_ifu.ifu_dstaddr
void *ifa_data; /* Address-specific data */
};