最近看到CSDN上的一篇博文,提到了从驱动代码里发现的一个奇怪宏,如下:

#define E1000_ROUNDUP(num, size) ((num) = (((num) + (size) - 1) & ~((size) - 1)))

那篇文章的作者通过执行代码认为此代码的作用是求能被size整除的大于或等于num的最小值(size要为偶数),并且没有给出解释。

实际上,这段代码的作用确实是求能被size整除的大于或等于num的最小值。但size的条件要示比较高,要为2的幂才可以。
我们可以试想这个宏是怎么想出来的。设size是2的n次幂,num共有m+n个二进制位。要求能被size整除的大于或等于num的最小值,可以分为2部分来考虑:整除和进位。

首先是进位。如果num没有恰好被size整除的话,肯定要在后n位加上待定的值来使前m位进1。暂且不考虑后n位,只要让前m位加1,即加上2的n次方即可达到目的。但是如果num正好能被size整除,就不能进位了。因此可以加上2的n次方减1(即size-1)。

再次是整除,要被size整除,也就是要把num的后n位清零,同时保证前m位不变(因为进位的要求已经达到了)。C语言位操作中的“与”操作常用来完成位清零和位保持的工作。只要将num与后n位为0的数作与操作即可将后n位清0。其余的二进制位与1作与操作即可保持相应位的值不变。因此,我们只要构造一个后n 位为0,其余各位为1的数即可。由于1的位数要根据num值的大小来确定,因此这个数不好构造。但后n位为1,其余各位为0的数很好构造,就是size- 1。只要将size-1的各位按位取反就可得到我们想要的数。因此整除的操作可以通过“&~(size-1)”来完成。

综合起来,就是num=(num+size-1)&~(size-1)。将它变成宏的时候要注意将各参数都用括号括起来,防止宏展开的时候出现错误。因此就有了开篇的那句代码:

#define E1000_ROUNDUP(num, size) ((num) = (((num) + (size) - 1) & ~((size) - 1)))

从这个宏我们可以看出位操作的强大功能。与2的幂相关很多问题都可以用位参数来实现。如果不用位操作,本题可以用用如下代码来实现:

num=(num%size==0)?num:(num+size-num%size);

或者

num=(num%size==0)?num:(num/size+1)*size;

很多时候我们都要求能被size整除的大于或等于num的最小值。比如Linux下的DES加密函数,要求只能对8字节的整数倍的数据进行加密,如果不是,就要在数据的后面补零变成8字节的倍数再进行加密。8正好是2的幂,补0后的字节数就可以用上面的宏来求。同样,将一段数据写到操作系统的分页(4096字节)里也可以用上述的宏。

同一个局域网中不能存在两个相同的IP地址,否则冲突。

因此不能直接用其他用户的IP地址伪造ARP响应,除非那个用户主机没开或宕掉(这就可以构成简单的ARP欺骗)。

在进行网络数据传送时,在数据发送方要经过以下几个步骤:应用程序-->socket-->传输层模块-->IP模块-->NIC(网卡)驱动程序-->硬件中断。

IP 模块在本机的路由表上查询出口IP,如果是本局域网的IP就直接交付,然后查找ARP缓存表把帧发送到目的主机。如果目的IP不在本局域网,路由表会提示将数据发到网关上。因此主机的网卡将目的MAC填上网卡的MAC地址,发到网关后。网关再根据目的IP地址转发此数据包。

为什么要经过ARP请求和响应,而不直接广播数据帧?因为数据帧可能比较大,局域网上的每个主机都要解析它,提取出IP地址看与自它是否与自己的一样,这样太浪费时间和带宽了。

ARP在哪一层?数据链路层。它没有用到IP协议,只是把IP地址封装到帧内。

如果在共享式局域网中,一台主机可以监测到其他主机的通信数据。而如果是在交换式局域网中,则不可以。因为冲突域已经被交换机给隔开了。

什么是网关?网关(Gateway)就是一个网络连接到另一个网络的“关口”。在Internet网中,网关是一种连接内部网与Internet上其它网的中间设备,也称“路由器”。网关实质上是一个网络通向其他网络的IP地址。

delicious是个很不错的网摘收藏与分享的网站,它的标签化管理做的非常出色。我常常用它来收藏自己喜欢的一些文章。

但是我在学校里的用的是教育网,如果访问delicous就必须要用代理,可是一些免费的代理总不是很稳定,偶尔会登录不上去。而我在 delicious上收藏的文章一般都是国内的文章,是没必要代理就可以访问的。所有用delicious就有点不太方便了。而且delicous每页显 示的文章链接数只有10条,看完100条链接的话要点击10次,实在让我有点心烦。

因此我用python写了个脚本,可以将某个用户的分享的文章链接全部下载下来,放到一个HTML文件中,这要以后就可以不登记delicious就可以点击这些链接了,也可以算是一种备份吧。

废话不多说了,以下是python的代码。

Python语言: Codee#1012

01 #encoding=utf-8
02 import sys,urllib2,re
03
04 user = 'laphy'
05 def tag2html(name,url,description):
06     global user
07     file_name = "rewen.html"
08     f = open(file_name,"a")
09     f.write("\t<DT><A HREF=\""+url+"\">"+name+"</A>\n")
10     if description:
11         f.write("\t<DD>"+description+"</DD>\n")
12     f.close()
13
14 def main(agrv=None):
15     page_num = -1
16     base_url = "http://www.zhuaxia.com/indexFrame.php#showPopular(4,25,%d)"
17     url = base_url % page_num
18     #f = urllib2.urlopen(url)
19     #data = f.read()
20     #nums_re = '<span id="tagScopeCount">(\d+)</span>'
21     #link_count = (int)(re.search(nums_re,data).group(1))
22     #page_count = link_count/10 + 1
23     #for page_num in range(2,page_count+1):
24    
25     while page_num<100:
26         page_num+=1
27         print page_num
28         url = base_url % page_num
29         data = urllib2.urlopen(url).read()
30         print data
31         #url_re = 'class="taggedlink " href="(.*)" >(.*)</a>'
32         url_re = 'href="(.*)" target="_blank" onclick="__305(500);">(.*)</a>'
33         urls = re.findall(url_re, data)
34         for i in urls:
35             tag2html(i[1],i[0],None)
36             print i[1]
37        
38    
39 if __name__ == "__main__":
40     sys.exit(main())


较新的博文 主页