Skip to content

回顾5月12日

当时下午两点过,我正在实验室调试程序,只觉得一声隆隆隆的声音传来;当时第一反应是中央空调的声音怎么这么大;然后冲出实验室往办公区望去,似乎没有什么动静;我刚愣了一下,就发觉地板开始剧烈颤抖;我马上意识到——地震了。

我立即向前台冲去,发现没有人;这时候震感小了一些,然后我又转回办公区;这个时候突然震感加剧,非常厉害,在原地都有些站立不稳,整栋楼已经晃得很厉害了(公司在8楼),吊顶的一些小物品开始掉下来;我立刻扶住身边的构造柱,然后转头看看后面,发现几个同事也都扶着柱子(事后知道还有其他同事已经钻到桌子下面去了);当时大家都有点紧张了。

突然震感又减轻了些,我朝办公区的同事们大喊,“快跟我走”,这个时候大家就跟我朝消防楼梯跑去;同时,另外一个部门的同事也都一起跑过去;大家一边喊着“快,快”,一边一个紧接一个的飞奔下楼梯来到的楼之间的空地上。

这个时候才稍微舒了口气,我赶紧给家里人打电话,发现都打不通;我马上就开车迅速地去找家人了;找到所有的家里人以后,大家才开始讨论今天发生的一切。

Tagged ,

一个不错的网站

http://www.filewatcher.com/

用来找软件很方便。

Tagged

Busybox中reboot命令的执行流程

在使用Busybox的嵌入式系统中,根据开发平台的不同,reboot命令不一定能够运行。而reboot作为一个标准的命令,直接使用它来重启系统,要比其它的方法更具有可移植性。下面就简要分析一下reboot命令的执行流程以及如何使它得以工作。

我们分析的是Busybox 1.0版本。

reboot的功能实现在,

# busybox/init/reboot.c - reboot_main()  

return kill_init(SIGTERM);
# busybox/init/init_shared.c - kill_init()  

return(kill(*pid, sig))

到这里,reboot实际完成了向init进程发送一个SIGTERM信号。到init的实现中查看相关的实现,

# busybox/init/init.c - init_main()  

signal(SIGTERM, reboot_signal);  

# busybox/init/init.c - reboot_signal()  

init_reboot(RB_AUTOBOOT);  

# busybox/init/init.c - init_reboot()  

reboot(magic);

这里的reboot实际上调用了

# cross-compiling-include/sys/reboot.h  

extern int reboot (int __howto) __THROW;

这样自然就会走到系统调用sys_reboot中

# kernel-src-path/kernel/sys.c  

asmlinkage long sys_reboot(...)  

{  

...  

machine_restart(NULL);  

...  

}

然后是

# kernel-src-path/arch/arm/kernel/process.c  

arch_reset(reboot_mode);

当然,执行arch_reset之前还有其他的一些清理工作。最后就走到

# kernel-src-path/include/asm/arch/system.h  

extern inline void arch_reset(char mode)  

{  

...  

}

这里就是最终的复位代码了,比如利用WDT来复位系统。

Tagged , ,

NAN,INF和-INF

在进行浮点运算的时候,一旦除数出现0值的时候,就会出现NAN,INF和-INF。NAN表示这个存储空间里面的内容不是一个数字(Not A Number),而INF和-INF则表示正负无穷大。

在GCC中,可以直接通过0.0/0.0,1/0.0和-1/0.0来构造这些特殊的“数字”,但是在VC2005中,只能通过先定义变量,然后再计算的方法来得到它们。

要注意的是,浮点数除了有效的数字外,还可能的取值就是NAN,INF和-INF。另外,INF和-INF是可以参与计算的,而NAN不可以。

Tagged ,

清明节

其他公司的朋友们都在家里呼呼大睡,我却在公司敲键盘。

:cry:

Tagged

maopian.com? fuckbaidu.com?

maopian.com

fuckbaidu.com

什么乱七八糟?网友恶作剧?

Tagged ,

利用UDP广播来寻找设备

当一个设备连接到局域网以后,我们可能不知道它的Static IP,也可能这个IP正好对于该网段是一个无效的IP,那么我们就需要通过数据链路层来发送UDP包来与设备通信,并设置有效的IP。

我们可以把整个过程分为两个阶段:DISCOVER阶段,CONVERSE阶段。

DISCOVER

 这个阶段比较简单。因为无论设备的IP是多少,只要正确建立基于UDP的socket,则设备就能够接收到网络上的广播。所以下面给出简单的示意代码:

int fd;
struct sockaddr_in my_addr;  

fd_set fdset;
struct timeval timeout;  

fd = socket(PF_INET, SOCK_DGRAM, 0);  

bzero(&my_addr, sizeof(my_addr));
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(SERVER_PORT);
my_addr.sin_addr.s_addr = INADDR_ANY;
bind(fd, (struct sockaddr *) &my_addr, sizeof(my_addr));  

FD_ZERO(&fdset);
FD_SET(fd, &fdset);      

timeout.tv_sec = TIMEOUT;
timeout.tv_usec = 0;      

select(fd + 1, &fdset, NULL, NULL, &timeout);
recvfrom(fd, buff, BUFFSIZ - 1, 0, NULL, NULL);
buff[BUFFSIZE] = '\0';

CONVERSE

与前一阶段相比,这个阶段稍微要麻烦一点。首先需要建立一个Packet socket:

fd = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP));

这里的SOCK_DGRAM指出这个socket是针对cooked packets,即packet中是没有link level header信息的。所以我们需要包含有link level header信息的结构体sockaddr_ll:

struct sockaddr_ll dest;
struct ifreq ifq;  

memcpy(ifq.ifr_name, "eth0", IFNAMSIZ);
octl(fd, SIOCGIFINDEX, &ifq);      

bzero(&dest, sizeof(dest));
dest.sll_family = AF_PACKET;
dest.sll_protocol = htons(ETH_P_IP);
dest.sll_ifindex = ifq.ifr_ifindex;
dest.sll_addr[0] = 0xFF;
dest.sll_addr[1] = 0xFF;
dest.sll_addr[2] = 0xFF;
dest.sll_addr[3] = 0xFF;
dest.sll_addr[4] = 0xFF;
dest.sll_addr[5] = 0xFF;
dest.sll_addr[6] = '\0';      

bind(fd, (struct sockaddr *) &dest, sizeof(dest));

这样,我们需要的link level header就设置好了。

接下来就是自行购建IP包和UDP包了:

struct { struct iphdr ip; struct udphdr udp; struct content data } packet;  

ioctl(fd, SIOCGIFADDR, &ifq);  

bzero(&packet, sizeof(packet));  

packet.ip.protocol = IPPROTO_UDP;
packet.ip.saddr = ((struct sockaddrin *) &ifq.ifr_addr)->sin_addr.s_addr;
packet.ip.daddr = INADDR_BROADCAST;
packet.udp.source = htons(SERVER_PORT);
packet.udp.dest = htons(DISCOVER_PORT);
packet.udp.len = htons(sizeof(packet.udp) + sizeof(packet.data));
packet.ip.tot_len = packet.udp.len;
packet.udp.check = checksum(&packet, sizeof(packet));
packet.ip.tot_len = htons(sizeof(packet));
packet.ip.ihl = sizeof(packet.ip) >> 2;
packet.ip.version = IPVERSION;
packet.ip.ttl = IOPDEFTTL;
packet.ip.check = checksum(&packet.ip, sizeof(packet.ip));

相关的成员设置可以参考TCP/IP的教程进行理解。

最后就可以将数据发送出去了:

sendto(fd, &packet, sizeof(packet), 0, (struct sockaddr *) &dest, sizeof(dest));

好啦!

用Wireshark抓一下包吧……记得设置成“非法”IP哦!    :smile:

Tagged , , ,

华为又走了一位年轻的精英

就在我们大楼旁边,前天又一位华为的兄弟用跳楼的方式轻易结束了自己的生命。为什么华为老是出这种事情呢?

联想到前段时间自己也觉得生活很乏味,不禁害怕了一下,看来心理健康真的是很重要,没有事就去走一走,运动一下,或者是疯狂 shopping 一次,都是很好的调剂手段。

另外,也据传是炒股巨亏,无力还债导致这名男子轻生。所以说投资还是需要量力而行,要学会自己控制风险,这才是生财之道。

Tagged ,

除错,整合,打包

每天都在除错,整合,打包……

相当的枯燥。

Tagged

Valentine’s Day

情人节快乐!

祝莎莎每天都快乐!

Tagged