Crane
Table_bottom

Search
Loading
Table_bottom

分类
Table_bottom

随机文章
Table_bottom

标签云
Table_bottom

最新评论
Table_bottom

链接
Table_bottom

功能
Table_bottom

程序员的Rose

非常适合这个时间程序员来送给心中的TA,如果有的话。看图上代码

<!doctype html>
<html>
<head>
<title>Love</title>
<meta charset="utf-8" />

</head>
<body>
	<h1> Honey, Happy Valentine's Day ! </h1>
<canvas id="c"></canvas>
<script>
    var b = document.body;
    var c = document.getElementsByTagName('canvas')[0];
    var a = c.getContext('2d');
    document.body.clientWidth; 
</script>
<script>
    // start of submission //
    with (m = Math) C = cos, S = sin, P = pow, R = random; c.width = c.height = f = 500; h = -250; function p(a, b, c) { if (c > 60) return [S(a * 7) * (13 + 5 / (.2 + P(b * 4, 4))) - S(b) * 50, b * f + 50, 625 + C(a * 7) * (13 + 5 / (.2 + P(b * 4, 4))) + b * 400, a * 1 - b / 2, a]; A = a * 2 - 1; B = b * 2 - 1; if (A * A + B * B < 1) { if (c > 37) { n = (j = c & 1) ? 6 : 4; o = .5 / (a + .01) + C(b * 125) * 3 - a * 300; w = b * h; return [o * C(n) + w * S(n) + j * 610 - 390, o * S(n) - w * C(n) + 550 - j * 350, 1180 + C(B + A) * 99 - j * 300, .4 - a * .1 + P(1 - B * B, -h * 6) * .15 - a * b * .4 + C(a + b) / 5 + P(C((o * (a + 1) + (B > 0 ? w : -w)) / 25), 30) * .1 * (1 - B * B), o / 1e3 + .7 - o * w * 3e-6] } if (c > 32) { c = c * 1.16 - .15; o = a * 45 - 20; w = b * b * h; z = o * S(c) + w * C(c) + 620; return [o * C(c) - w * S(c), 28 + C(B * .5) * 99 - b * b * b * 60 - z / 2 - h, z, (b * b * .3 + P((1 - (A * A)), 7) * .15 + .3) * b, b * .7] } o = A * (2 - b) * (80 - c * 2); w = 99 - C(A) * 120 - C(b) * (-h - c * 4.9) + C(P(1 - b, 7)) * 50 + c * 2; z = o * S(c) + w * C(c) + 700; return [o * C(c) - w * S(c), B * 99 - C(P(b, 7)) * 50 - c / 3 - z / 1.35 + 450, z, (1 - b / 1.2) * .9 + a * .1, P((1 - b), 20) / 4 + .05] } } setInterval('for(i=0;i<1e4;i++)if(s=p(R(),R(),i%46/.74)){z=s[2];x=~~(s[0]*f/z-h);y=~~(s[1]*f/z-h);if(!m[q=y*f+x]|m[q]>z)m[q]=z,a.fillStyle="rgb("+~(s[3]*h)+","+~(s[4]*h)+","+~(s[3]*s[3]*-80)+")",a.fillRect(x,y,1,1)}', 0)
    // end of submission //

</script>
</body>
</html>

Tcpdump抓包重放

开发工作中经常有这样的场景,和同事联调的时候,对方发了一个测试包过来,这边用tcpdump –Xlnsp0抓到包了,但是程序结果不正确,然后自己debug,修改,然后需要再测试,这时候再让同事发一个?如果不正确,这一来一回的比较慢,如果有个工具自动把tcpdump抓下来的内容再发出去,就ok了。

于是问题就是这样的,比如用tcpdump –Xlnps0抓到一个udp包,然后用工具把这个包重新发出去。

 

继续阅读

Linux下用g++编译共享库的一个问题

最近在使用linux下的共享库so的时候遇到一个奇怪的问题,做个记录,方便备查。

一般来说,如果用gcc编译的时候加上-shared和-fPIC选项,可以把源文件编译成一个so文件,可以在其他源程序连接阶段把这个链接上去,从而可以调用so文件提供的函数接口,这样可以多文件共用一个so文件提供的函数,即节省内存空间,也便于更新,所有的接口只需要更新so文件就行。

其实除了上面的方法,还有一个方法,那就是在运行时由程序自己动态加载so文件,使用一系列系统调用如dlopen,dlsym,dlclose等来进行动态加载,获取函数地址从而进行函数调用,关闭加载的so文件等。

一般以第一种方法用得多,但是第二种方法更灵活,结合配置文件,更具一般意义上的服务扩展性。 但是就是在用第二种方法的时候出现了一点问题。

这里把问题抽象一下,假设有一个源文件是要编译为so文件的,假设这个源文件只提供一个简单的函数,add,取两个整数为参数,返回它们的和,源文件为add.c,代码如下:

#include <stdio.h> 
 
int add(int a, int b) 
{ 
    return a+b; 
} 

编译

gcc -shared -fPIC add.c -o libadd.so

 

然后写个脚手架程序来测试,test.c,代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>

int main(int argc, char *argv[])
{
    void * handle;
    int (*func)(int, int);
    char *error;

    handle = dlopen("libadd.so", RTLD_LAZY);
    if(!handle)
    {
        fprintf(stderr, "%s\n", dlerror());
        exit(1);
    }

    func = (int (*)(int,int))dlsym(handle, "add");
    if((error = dlerror()) != NULL)
    {
        fprintf(stderr, "%s\n", error);
        exit(1);
    }

    func(3, 4);
    dlclose(handle);

    return 0;
}
 

编译

gcc test.c -o test -ldl

然后修改LD_LIBRARY_PATH变量,加上库所在的目录,这里是当前目录

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:.
 

好的,这样是没有问题的,这样的方法是标准的动态加载so库的方法,但是问题在什么地方呢,如果把gcc换成g++,问题就出现了 整个编译完成后,执行test,它会告诉你

./libadd.so: undefined symbol: add
 

找不到符号add 然后用nm看一下libadd.so的符号名

$ nm libadd.so |grep add

00000000000005ec T _Z3addii

它娘的,这是c++编译器的符号命名法,用c++filt看一下

$ c++filt _Z3addii

add(int, int)

看吗,这才是我们很显而易见的函数名 所以,解决方案出来,把库源文件的函数当C符号来处理,这样

extern "C" {
// the function code
...
}

然后编译运行,这就是好的,编译出来后用nm看一下

$ nm libadd.so |grep add

00000000000005dc T add

哈哈,这就好了,然后在dlsym中写符号名的时候就直接写add就行了。

这里例子虽然是用g++编译纯C文件,其实是真正的cpp文件也是可以的。

打造ArchLinux下的类apt-get source工具

首先广告一下,Arch Linux 是我用过的最喜欢的一个Linux发行版,它是一个滚动升级模式的i686/x86-64 Linux发行版,它的开发注重于系设计简洁、结构优雅、代码 准确、体验新潮的完美权衡。它给你一个最小的系统,但是提供很强大的包管理,从而你可以自由的构建一个理想的系统,它的包管理强大之处在于它有两套包管理系统,一个是基于pacman的二进制包管理系统,类似ubuntu下的apt-get 系统,使用官方仓库,提供大量打包好的软件包可供直接使用,另外一个就是全功能的类ports的ABS(Arch Build System)软件包管理系统,类似gentoo的emerge系统,可以很方便的从源码构建软件,而且构建出来的软件也纳入pacman的包管理系统,这样就可以方便的缷载软件,避免了最普通的configure&&make&&make install这一种从源码构建方式不易缷载的问题。ABS实际上维护了一个PKGBUILD文件集合,其中每个PKGBUILD文件对应一个软件,可以使用makepkg命令来通过PKGBUILD构建软件。ABS其中的软件包是社区维护用户的,任何人都可以提交可以构建软件的PKGBUILD,从而形成了一个非常巨大的仓库,这个仓库就叫AURArch Linux User-community Repository)。

继续阅读

计算两个日期的差值

记得今年早些时候看到百度员工出的那个视频,中间有一幕女主角在计算自己自出生以来已经生活了多少天,只见她熟练的打开excel,在A1中输入生日,在B1中输入当天日期,在C1中输入=B1-A1,立刻得到自己来到这个世上的时间,眼看过去了这么多天,自己当初的梦想实现了多少呢,……,剧情自此展开,不再追踪。

我看到这个的时候,想着cli控们有没有什么方法能实现同样的功能呢,无所不能的shell(我记得有人说过shell是完备的)啊,需要你的力量。

想了一下,使用了coreutils中的date命令,写成了如下shell脚本:

 

继续阅读