emc的4道面试题自解

1.int main() {
  fork();
  fork()&&fork()||fork();
  fork();
}
问:共创建了多少进程?

这道题我第一个映像就是短路求值,然后又想到了几何级数,以及fork函数,fork后还有fork

我的答案是20-1=19。前边的20是进程总数,后边-1是创建进程数

第一个fork完后共用2个进程(ID=1,ID=2),第二个fork,当返回值为0时,即子进程时,直接调用倒数第二个fork,于是ID=1,ID=2分别调到第二个fork,然后各调到倒数第二个fork,共形成了8个进程

第二个fork不为0时,即进程为母进程或第一个子进程时,则要看第二个fork如果第二个fork也不为0的话,则不用考虑第三个进程,最先存在两个进程调用最后的fork,然后形成了4个进程

第二个fork!=0,第三个为0时,则需要调用后边两个fork,则为2X2X2=8

所以除去最开始的进程,一共创建19个进程
2.#define NELE(a) (sizeof(a) / sizeof(a[0]))
  int main() {
    char str[] = {‘E’, ‘M’, ‘C’};
    for (int d=-1; d<=(NELE(str)-2);d++)
      printf("%c",str[d+1]);
    return 0;
  }
问:输出结果

什么都没输出,根据C99文档,sizeof是无符号的数,当表达式中出现了个无符号的数时,所有有符号转化成无符号,则-1将变成一个巨大的值,那么直接return了
3.int i=1;
  printf("%d,%d\n",sizeof(i++),i);
  问:输出结果

4,1

sizeof()在编译前就处理了,因此sizeof(xxx)就是求的是int的大小,而++被忽略了。。。
4.#define f(a,b) a##b
  #define g(a)   #a
  #define h(a)  g(a)

  int main() {
   printf("%s\n",g(f(1,2)));
   printf("%s\n",h(f(1,2)));
   return 0;
  }
  问:输出结果
12

ascii12代表字符

 a##b字符12

#define g(a)   #a引用字符12

 #define h(a)  g(a) g(a)被字符12代替,然后理解为了数字12

Http 协议中ETag的用法

大网站一般都是用F5或其它的负载均衡设备,用户的每次请求落在那台real server都是不一定的,一次偶然的机会,发现相同的一个资源在两次访问时,http头中的etag是不相同的,主要是该资源一定是没有被修改的,于是想到etag的算法中可能使用到了资源在不同real server上可能不同的因子,于是参考了一下apache的文档(因为我们使用的是apache),文档地址:
http://lamp.linux.gov.cn/Apache/ApacheMenu/mod/core.html#fileetag

默认情况下,etag和资源的inode有关系,而inode在不同的real server上基本是不相同的,于是,这样的etag还不如没有,因为这样该资源是每次都要返回全部信息的,可以修改apache配置文件,添加如下配置:

FileETag MTime Size

这样修改后,如果文件没有发生变化,则只需要返回304就行,不需要返回所有内容了。
如果不做这样的设置,对于使用f5的情况,etag或许还不如没有。

关于apache中etag的算法,可以参考源码: src/main/http_core.c 中的函数set_etag_bits

那么,你的apache是怎么配置的呢?随便访问一个能返回etag的资源,etag类似:
ETag: "1e50006-22d0-4ba718e6"

如果是“-”分隔的3部分,字基本是包含inode、mtime、size了,如果是两部分,那就是其中的两项了,注意,每一项产生的长短不是固定的,不能按照长短来分析。

memcache-2.2.4 中对key的转换

一次在使用PHP的memcache-2.2.4模块访问mc时,不小心把含有tab的字符串做了key,在跟踪时发现我的key中出现tab的地方都成了“_”了,于是怀疑memcache-2.2.4对我的key做了处理了,于是看了memcache-2.2.4的源码,才发现如下函数,该函数里面将assii码小于空格的字符都要转换成“_”的。

int mmc_prepare_key_ex(const char *key, unsigned int key_len, char *result, unsigned int *result_len
 TSRMLS_DC)  /* {{{ */
{
    unsigned int i;
    if (key_len == 0) {
        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Key cannot be empty");
        return MMC_REQUEST_FAILURE;
    }

    *result_len = key_len < MMC_KEY_MAX_SIZE ? key_len : MMC_KEY_MAX_SIZE;
    result[*result_len] = ‘\0’;
   
    for (i=0; i<*result_len; i++) {
        result = ((unsigned char)key) > ‘ ‘ ? key : ‘_’;
    }
   
    return MMC_OK;
}

Ubuntu 上的vpn server 与 lvs

   今天突然又想起来了lvs,因为不需要硬件,就想自己也安装一个体验一下,由于windows上都不支持,所以就选择了我的Ubuntu;看了一些文档,发现安装太挺麻烦,都需要给内核打补丁,后来在新德里软件包管理器里找了一下,发现里面有了ldirectord,就是我要找的lvs, 还有pptpd,就是我要找了vpn server了,先不管怎么编译了,安装上试试吧。
   今天太晚了,以后再研究吧。
         

关于crontab中启动进程

      今天发现一个进程在
      futex(0x33a120, FUTEX_WAIT, 2, NULL <unfinished …>

      处“阻塞”,反正不往下运行了,就暂且叫“阻塞”吧,而且ps时发现进程状态为“Ss”,看到“s”,我以为是一个deamon,这是一个PHP程序,我 看了看代码,发现里面没有任何关于deamon的处理,也没有while、for等循环语句,怀疑不是一个deamon,但是“s”是怎么出现的呢?
      后来发现该进程是从crontab启动的,难道crontab启动的进程都会有“s”,测试了一个程序,确实是这样的。
      至于为什么在futex处阻塞,明天再仔细看看源码吧。

    关于futex (‘Fast Userspace muTexes’)的相关资料:
    http://linux.die.net/man/7/futex
    http://javadino.blog.sohu.com/99256728.html

只需更改文件名 iPhone可轻松超频

  北京时间5月16日消息,据国外媒体报道,日前有黑客发现了一种给苹果iPhone超频的简单方法,只需更改文件名即可。

  据悉,原本iPhone 3G处理器的时钟频率为600MHz,iPhone  3GS为833MHz,但出于多种因素考虑,其分别被苹果限制在了412MHz和600MHz。

  而此次黑客发现的这种超频方法,只需重命名一个文件即可。该文件名为“com.apple.SystemPowerProfileDefault.plist”,只需将其更名为“SystemPowerProfileDefaultbak.plist”,然后重启,即可轻松完成超频。

  友情提醒:通常,企业限制处理器时钟频率是为了节能、降低热量、延长处理器寿命。如果超频,可能导致设备过热,甚至被损坏,所以小编建议机友们切勿轻易尝试。

rewrite 用法点滴

1. 多个连续的RewriteCond 之间默认是“与”的关系,可以通过 [OR]来说明是“或”的关系, RewriteCond只作用于紧接着的一个RewriteRule

2. RewriteCond的flag有两个可选值: NC: 不区分大小写; OR:表明是“或”的关系

3. RewriteRule的flag常见值有两个:
[P]: 说明
立即中断重写处理,然后把处理移交给mod_proxy模块, 如果说立即中断重写处理,则[P,L] 中的L又有什么意义呢?
[L]: 相当于break,不要再继续匹配了,如果这条规则匹配上了,则这就是最后一个匹配了
不常见的几个flag:
[N]: 相当于continue,用当前已经重写好的url再从头开始继续匹配;这样写很难理解,所以很少有这样用的。
[F]: 禁止访问
[R]: 强制重定向,而不是直接代理,对于下面情况R就是多余的,因为没有P标记,则一定是强制重定向:

程序员与软件工程师

   我从来不知道程序员和软件工程师有啥区别,也没有想过程序和软件有啥区别。终于,我越来越发现一个问题,就是,我写程序的水平一定越来越高了,但是我却越来越质疑我的程序的价值了;我可能用了很长时间写出来的程序,根本是没有什么价值的。
   一个偶然的机会,我开始思考“程序员”和“软件工程师”这两个概念,我想,它们一定是不一样的,我的理解是:
   程序员关心的是程序的正确性和效率,不关心程序的价值,程序员写程序就像某些人打游戏,图的是自己快乐;
   软件工程师关心的更重要的是软件的价值,如果该软件不会给他带来渴望的利润,你们即使再好玩,他也不会去做的;既然如此,软件工程师也一定更关心软件的管理了。

   我现在非常渴望学习一些软件项目管理的知识,看来我更加关心实际利益了;原来图的是好玩,靠的是兴趣;现在图的是利益,为的是生计。

virtubox 中设置共享目录

VirtualBox可以通过分配数据空间来实现主机和虚拟机之间的数据交换。首先要给虚拟机安装增强功能包,然后在“数据空间”里面添加一个固定分配的数据空间,名称改为share(名称可以任意定)。

如果是Linux系统,以Ubuntu为例,假设挂载目录是/home/testuser/sharefile,直接在终端执行下列命令即可:
sudo mount -t vboxsf share /home/testuser/sharefile/

注意:
1. share为分配数据空间时点名字
2.  /home/testuser/sharefile/ 需要是一个存在点空目录

这个时候打开sharefile文件夹,里面就是share中的文件内容了。如果要取消挂载,使用下列命令:
sudo umount /home/buwood-vbox/Desktop/sharefile/

然后在VirtualBox取消分配空间即可。

如果是Windows系统,进入cmd,执行下列指令:
net use z: \\vboxsvr\share

在资源管理器里面就会多出一个网络映射驱动器z,里面是share中的文件内容。如果取消的话,直接在驱动器上点右键,选择“断开”即可,然后在VirtualBox取消分配空间。