Archive for February, 2009

关于sem_open(3)

February 15th, 2009

今天新闻组上有人问到这么个问题,为什么sem_open("/tmp/nimeni",O_CREAT|O_EXCL,SHM_MODE,1);总是得到ENOENT?

翻开sem_open的man手册看看,我们大体就会知道,第一个参数有问题,man手册中这么说:

sem_open(3):

sem_open() creates a new POSIX semaphore or opens an existing
semaphore.  The semaphore is identified by name.  For details of
the construction of name, see sem_overview(7).

sem_overview(7):

Named semaphores
A named semaphore is identified by a name of the form
/somename.  Two processes can operate on the same named
semaphore by passing the same name to sem_open(3).

我看了下面一个人的引用,发现我实在是没看man手册的必要了,这里的描述有问题!所以我找到了sem_open()在glibc中的实现(nptl/sem_open.c):

C:
  1. //....
  2.   if (mountpoint.dir == NULL)
  3.     {
  4.       __set_errno (ENOSYS);
  5.       return SEM_FAILED;
  6.     }
  7.  
  8.   /* Construct the filename.  */
  9.   while (name[0] == '/')
  10.     ++name;
  11.  
  12.   if (name[0] == '\0')
  13.     {
  14.       /* The name "/" is not supported.  */
  15.       __set_errno (EINVAL);
  16.       return SEM_FAILED;
  17.     }
  18.   size_t namelen = strlen (name) + 1;
  19.  
  20.   /* Create the name of the final file.  */
  21.   finalname = (char *) alloca (mountpoint.dirlen + namelen);
  22.   __mempcpy (__mempcpy (finalname, mountpoint.dir, mountpoint.dirlen),
  23.              name, namelen);
  24.  
  25.   /* If the semaphore object has to exist simply open it.  */
  26.   if ((oflag & O_CREAT) == 0 || (oflag & O_EXCL) == 0)
  27.     {
  28.     try_again:
  29.       fd = __libc_open (finalname,
  30.                         (oflag & ~(O_CREAT|O_ACCMODE)) | O_NOFOLLOW | O_RDWR);
  31.  
  32. //....

所以这里的问题其实很简单,最根本的问题是那个path参数就究竟是用来干什么的?用一句话说,其实就是指定一个文件位置,这个位置是以tmpfs的挂载点为根目录的。也就是说,如果它以/开头,说明是从tmpfs根目录开始,而如果不是,就是从相对路径开始,不过“当前目录”也是根目录(这正是为什么sem_open()的实现中会去掉开头的/)。到了这里我们可以看出一开始那个问题的原因了,它传递的是"/tmp/nimeni",也就假设了tmpfs的挂载目录(通常是/dev/shm)下有tmp这个目录,而事实上没有,所以即使他加上了O_CREAT|O_EXCL也会返回ENOENT。

所以,传递给sem_open()的第一个参数究竟怎么写才好呢?"/somename"和"somename"都可以,都容易读而且也都对,但是名字中间有/就不行了。

从上面我们也可以看出,对于程序员来说,有些时候啊,读文档真的还不如直接去读代码来得更快!所以这也提示我们:代码要写得像文档一样易读!我坚信好的代码就应该如此!

唉,情

February 14th, 2009

唉,今天又是情人节,可是年年都和我无关。不过比较公平的是,情人节过不了我可以过光棍节。:-)

前几天和小林子聊天时聊起了我们这些兄弟们的感情问题,起因是老大的somebody,我们简单地总结了一下:

老大:上大学的时候就很受欢迎,身边经常是小姑娘成群,妹子一大把。毕业以后又以迅雷不及掩耳盗铃之势又泡了一个他所谓的somebody~!所以在兄弟当中,他是当之无愧的最幸福的一个!要不是小林子提示,我都没看出来,原来某人的文章中还暗示了过3年我们就该给他们的婚礼送红包了现在得先提前准备着~!

小林子:上大学的时候和王敏华同学好上了,记得当时传得满系风雨,我和小公子惊讶了好久……不过他们毕业后分了,但起码曾经有过,所以仍然算是不错的~~而且小林子现在所在的公司美女很多,找到下一个应该不是什么问题!

DP:比较痴情的一个娃,可以看他的博客。他曾经有过一段时候喜欢一个女孩,后来不知道怎么就分手了,反正不是人家DP的错,DP到现在还对她恋恋不舍。真是“爱过方知情重”啊!希望DP早日找到一个更合适的。

Kermit Mei:速度和老大有一拼,也是以“闪电战”搞定一个我们迄今为止还没见过的女生(小林子除外)。虽然工作还没搞定,但有个女朋友起码也是一种安慰,也算是不错!

金经理:这个貌似和我一样都是没谈过恋爱的,但是,据内部不愿透漏姓名的小林子同学透露,金主席(注意头衔的变化)当年是感情相当丰富滴,然后$%@#。而且,人家经理现在早已有目标了哦,就是他那个传说中的爱笑的眼睛~!希望经理可以早日搞定。

相比之下我是最惨的一个,三年没谈过恋爱,现在别说目标,就是连个人影都没看到呢!!虽然我一直喜欢折腾这无聊的生活,但说实话,偶尔有些时候还真是感觉挺孤单的,想找个说话的人都没有……唉,现在找女朋友也不是为了别的,就为了无聊的时候能找个人说说心里话。而这我看也很悬……

不抱怨了。祝上面提到的那些有情人们终成眷属!就像下面这个flash中的说的:“你叫声老拐,她叫你声老头子,那小日子过得是多么滋润呐,多么滋润!”

P.S. 很老的一个flash了,《爱情上甘岭》,一直比较喜欢。

Happy Birthday, UNIX!

February 14th, 2009

% python -c 'from time import strftime, localtime; print strftime("%a, %d %b %Y %H:%M:%S", localtime(1234567890))'
Sat, 14 Feb 2009 07:31:30

% date -d '@1234567890'
Sat Feb 14 07:31:30 CST 2009

% perl -e 'print scalar localtime(1234567890),"\n"; '
Sat Feb 14 07:31:30 2009

查找网络设备

February 12th, 2009

在新闻组上看到有人问如何通过名字查找某个网络设备,其实不难,首先想到的就是通过ioctl,示例代码见下:

C:
  1. int get_interface(const char *interface)
  2. {
  3.     int sock = socket(PF_INET, SOCK_STREAM, 0);
  4.     struct ifconf ifc;
  5.     struct ifreq *ifr;
  6.     int ret = -1;
  7.  
  8.     if (sock <0)
  9.         return -1;
  10.  
  11.     ifc.ifc_len = 0;
  12.     ifc.ifc_req = NULL;
  13.     if (ioctl(sock, SIOCGIFCONF, &ifc) <0)
  14.         goto close;
  15.  
  16.     if (ifc.ifc_len> 0) {
  17.         ifc.ifc_req = malloc(ifc.ifc_len);
  18.         if (ifc.ifc_req) {
  19.             if (ioctl(sock, SIOCGIFCONF, &ifc) <0) {
  20.                 free(ifc.ifc_req);
  21.                 goto close;
  22.             } else
  23.                 for (ifr = ifc.ifc_req;
  24.                      (char *)ifr <
  25.                      (char *)ifc.ifc_req + ifc.ifc_len; ++ifr) {
  26.                     /*printf("%s\n", ifr->ifr_name);*/
  27.                     if (!strcmp(ifr->ifr_name, interface)) {
  28.                         ret = 0;
  29.                         break;
  30.                     }
  31.                 }
  32.         } else
  33.             return -1;
  34.  
  35.         free(ifc.ifc_req);
  36.     }
  37.  
  38. close:
  39.     close(sock);
  40.     return ret;
  41. }

然后有人说POSIX其实还有个if_nameindex(),它明显要比ioctl可移植性要高,用它重写上面的代码如下:

C:
  1. int get_interf(const char *interf)
  2. {
  3.  
  4.     int ret = -1;
  5.     struct if_nameindex *ifp, *ifpsave;
  6.     ifpsave = ifp = if_nameindex();
  7.  
  8.     if (!ifp)
  9.         return -1;
  10.  
  11.     while (ifp->if_index) {
  12.         if (strcmp(ifp->if_name, interf) == 0) {
  13.             ret = 0;
  14.             break;
  15.         }
  16.         ifp++;
  17.     }
  18.  
  19.     if_freenameindex(ifpsave);
  20.     return ret;
  21. }

我查了一下glibc中的实现,发现在linux上其实如果不用netlink的话,if_nameindex()也就是对ioctl(...SIOCGIFCONF...)的一个包装,具体可参考sysdeps/unix/sysv/linux/if_index.c。netlink这个东西够奇怪的,在这里居然也能派上用场,有机会要研究研究~

据说是世界上最好的工作。。。

February 11th, 2009

猜猜是什么?科学家?高管?总统?都不是!是大堡礁岛屿看护员!

为什么是世界上最好的呢?首先工作环境狠好!在几乎是天堂的旅游胜地工作——世界自然遗产大堡礁。然后是待遇狠高!半年就能拿到15万澳元!工作也轻松啊,喂个鱼,送个信什么的……此外住宿啊,交通费啊,上网什么的人家全都包!!美死了都,直流口水……那个旅游局真有钱……

有兴趣的看官方网站的介绍吧:职位描述待遇及挑选标准挑选过程

唉,眼红死了都,我是达不到要求的,我还是擦干净口水,老老实实当我的程序员吧~~~!

P.S. 附关于程序员的冷笑话一则:

——我是程序员。
——哦,程先生!
——客气了,叫我序员就好。

《一日重生》

February 10th, 2009

这本书写得很别致,很短小,而且文字并不华丽,但却直指心灵深处,读完后内心深处有一种莫名的触动。

书中的故事无疑是虚构的,但它却不离谱。一个堕落的人走上了自杀的道路,刻意制造了一场车祸,然后昏迷中梦到和逝去的母亲重逢,并一起度过一天,在这一天中还反复穿插着母亲还活着时自己的点点滴滴,对自己的行为感到后悔不已……

看看主人公的话,我们不都是,或者曾经是,和他一样吗?

“如果把应该和妈妈在一起而没有在一起的时间累加起来,恐怕也有一辈子那么长了。”

“妈妈过世后多年后,我给自己列了两个清单,一张单子上列着妈妈为我挺身而出的事情;另一张单子上列着我没有为妈妈挺身而出的事情。很悲哀,两个单子长短差距很大。为什么对于爸爸妈妈,孩子会向其中的一个,索取很多很多,而对另一个,却没有太多的要求呢?

书中的母亲说的几句话更是让我们这些做孩子的感到羞愧:

“孩子们常常因为父母的缘故而感到尴尬,”

“有时候,孩子的话最伤人,是不是,罗丝?你忍不住要问,‘这究竟是谁的孩子?’”

“但通常,他们是因为受了伤才这样做。他们想要找到一个解决的办法。”

一个因为母亲而感到羞愧的孩子,只不过是个没有长大的孩子罢了。

多为爸妈做些什么,相对于他们的付出,其实他们要求的并不多。

知识共享许可协议
本作品采用知识共享署名-非商业性使用-相同方式共享 2.5 中国大陆许可协议进行许可。
葡驻京办ICP备07006283号