分类: '编程相关' 的归档
linux进程间通信──消息队列
linux自古以来就是一个多任务多用户的操作系统,所以linux的进程间通信(Inter-Process Communication──IPC)就显得非常重要了。
IPC是一种标准的Unix通讯机制,目前有以下几种通讯方式:管道(Pipe)、信号量(Semaphore)、互斥体(Mutex)、共享内存(Shared Memory)和消息队列(Message Queue),当然也有其他的方式,比如文件系统和dbus等。
今天我就来介绍一种简单实用的进程间通信方式:消息队列(Message Queue)。
首先说说消息队列的优缺点:
1.消息队列只适用于单台主机的进程间通信,如果是不同主机,需要用socket等其他方式,也就不属于IPC的范畴了。
2.消息队列可以实现异步通信,这似乎是优点,但说是它缺点也是可以的:通讯往往不是实时的。
3.消息队列有大小限制,通常只用于小数据量的发送。系统对用户的大小限制可以通过 ulimit -q 命令进行查询。
4.消息队列可以实现阻塞调用和非阻塞调用。
5.实现简单,且可移植性好。
下面通过一个实例来进行说明,以下文件保存成 ipc_msg.c:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/msg.h> int main(int argc, char *argv[]){ int ipc_key,msg_id,msg_len; long mtype; void * mbuf; if(argc==5 && argv[3][0]=='s'){ ipc_key=atoi(argv[1]); mtype=atol(argv[2]); msg_len=strlen(argv[4]); if ( 0>(msg_id=msgget(ipc_key, 0666|IPC_CREAT)))return 1; if ( NULL==(mbuf=malloc(msg_len+sizeof(long)+1)) )return 2; memcpy(mbuf, (void *)&mtype, sizeof(long) ); memcpy(mbuf+sizeof(long), (void *)argv[4], msg_len ); if ( 0>msgsnd(msg_id, (struct msgbuf *)mbuf, msg_len, 0) )return 3; printf("Send Success.n"); }else if(argc==4 && argv[3][0]=='r'){ ipc_key=atoi(argv[1]); mtype=atol(argv[2]); if ( 0>(msg_id=msgget(ipc_key, 0666)))return 1; if ( NULL==(mbuf=malloc(4096)) )return 2; if ( 0>(msg_len=msgrcv(msg_id,(struct msgbuf *)mbuf, 4000, mtype, IPC_NOWAIT))){ printf("No message received.n"); return 3; } printf("Recv Success.(%d bytes):n",msg_len); printf("%sn",(char *)(mbuf+sizeof(long))); }else if(argc==3 && argv[2][0]=='c'){ ipc_key=atoi(argv[1]); if ( 0>(msg_id=msgget(ipc_key, 0666)))return 1; if ( 0>msgctl(msg_id,IPC_RMID,(struct msqid_ds *)mbuf) )return 2; }else{ printf("usage:" "%s key type s message --to send messagen" "%s key type r --to receiven" "%s key c --to clear queuen" ,argv[0],argv[0],argv[0]); } return 0; }
以上程序,实现了发数据到消息队列和从消息队列收取数据的功能。
第一个参数需要是一个整形数值,表示消息队列的Key;
第二个参数是一个长整形的数值,表示消息的Type,Key+Type 可以唯一确定一个先进先出的消息队列。
第三个参数如果是‘s’则把第四个参数发到指定消息队列,如果是‘r’则从指定消息队列收取消息,并打印。
另外,如果第二个参数是‘c’,则把Key对应的队列删除。
让我们来运行一下试试:
$ gcc -o ipc_msg ipc_msg.c #编译 $ ipcs -q ------ Message Queues -------- key msqid owner perms used-bytes messages #一开始系统中没有消息队列。 $ ./ipc_msg 1 2 s abc Send Success. #发送了一个内容为abc的消息 $ ipcs -q ------ Message Queues -------- key msqid owner perms used-bytes messages 0x00000001 262144 lily 666 3 1 #发送了一个消息以后,队列里有消息了,key是1,有3个字节。 $ ./ipc_msg 1 2 r Recv Success.(3 bytes): abc #从消息队列成功收到消息了。 $ ipcs -q ------ Message Queues -------- key msqid owner perms used-bytes messages 0x00000001 262144 lily 666 0 0 #收完以后,空的消息队列仍然存在,不会自动消失。 $ ./ipc_msg 1 c #删除队列 $ ipcs -q ------ Message Queues -------- key msqid owner perms used-bytes messages #成功删除了,回到原始状态。
本文以GNU自由文档许可证发表.
python用着太顺手了
(此文纯属自言自语,基本可以忽略,呵呵.)
python用着太顺手了,其实是很久以前就有这种感觉,最近印象比较深的一次就是在做Project Euler的第一题的时候,那题比较简单,要求1000以内所有能被3或5整除的自然数之和.这题其实用什么语言都不复杂,但是用python的话,只需要一行:
sum([n for n in range(1000) if n%3==0 or n%5==0])
接近自然语言的表达看起来好舒服,而且也相当简洁.
然后今天,我又更新了一下gmbox,基本上把CLI重新写了一遍,又有同样的感觉了.gmbox的命令行,分交互式和非交互式两种,刚好用cmd和optparse两个内置模块轻松搞定.而且cmd模块支持欢迎界面/自定义提示符/readline库;optparse支持长短选项和混杂无序的选项,并自动生成帮助界面.真是太爽了.这两种模式加起来才140行左右的代码.去掉文件头,只有120行…
以后继续学习python.哈…
bones7456 WP theme 微调
看到Matrix 67的blog的主题,觉得有一点很不错:就是右侧的最新评论那里,一开始是每个评论只占据一行的位置,只有在鼠标放上去的时候,才会把内容展开.
这样的好处很明显:平时节省页面空间,布局也更漂亮,鼠标放上去的时候显示出该有的信息,也不影响使用.
于是,有样学样,把这一小细节学习了过来(呃..好吧,其实就是抄了过来…).
在实现上,没去动WP带的dynamic_sidebar函数,而是偷懒了一下,在页面基本展开完以后,用js处理了一下style,并添加事件函数.看现在是不是更好看了?
之前我都只敢放5个最新评论,因为再多,就不美观了.现在放10个也不是问题.
如果你也喜欢并想试试本WP主题,可以到这里下载最新的代码.
:-)
谷歌音乐下载器
之前有很多下载baidu mp3的程序,有bash的,java的,python的,其中也包括我这个.
但是baidu的歌曲都是用程序收集自网络的,所以排行榜的歌曲质量就没有保障了,下载下来的歌曲ID3信息可谓一塌糊涂,而且还可能下载到网友自己翻唱的歌或者其他杂七杂八的东西,严重影响我们的听觉神经.
而谷歌(不是google)最近推出了谷歌音乐搜索,联合top100,也推出了类似百度榜单的音乐排行榜.但不同于百度的是,谷歌里的歌曲都是收集整理过的,不会有死链,质量也很不错,而且,对于最终非商业用途的个人用户而言,是不存在版权问题的(但我不确定批量下载下来的有没有版权问题.请用户自行考虑.).
所以我顺势就推出了这个谷歌音乐下载器 .
目前程序还很简陋,没有图形界面,也没有很多可以设置的地方.运行程序只会把”华语新歌”这个榜单的100首歌下载到本地当前目录.所以仅供有兴趣尝鲜的同学测试使用.但是以后,我打算把这个程序做成有图形界面的,可以试听/下载/播放的一个整合工具,哈哈.请大家多多关注吧.
PS:有人说这类工具还是不要发布出来,小范围流传下比较好,因为发布出来以后,很可能遭到google的封杀.这说法其实也有些道理,但是我想想,如果谷歌真的因为这个来封杀我,我也够有面子的,嘿嘿.所以我还是按照Google的Project hosting页面所说的做了: Release early, release often
SQLite简介
SQLite大致就是”SQL lite”,也就是一个微型的SQL解释器.它的赞助商和使用者包括mozilla,adobe,symbian等软件巨头,也算是来头不小了.
说它微型,那么它到底有多微型呢?我们可以看看它的可执行文件的大小,linux版本的打包文件是203.93 KiB,解压以后是350.88 KiB,是不是很微型呢?
除了微型之外,SQLite主要还要以下特点:
- 无须配置: SQLite不需要安装,直接解压可执行文件即可运行.
- 没有服务进程: SQLite无须通过TCP/IP等通信协议提交SQL到服务端,处理后再返回结果.
- 单个数据文件: SQLite将用户数据存于单个普通文件里面.也就是说用户只要有数据文件的读权限,就可以读取所有数据;有写权限也能改变数据.
- 数据文件可跨平台迁移: SQLite本身是跨平台的,它的数据文件同样也是跨平台的.数据文件和平台的字节序无关,也和CPU的位数无关.直接复制数据文件就可以实现数据迁移.
- 紧凑: 如上所述,SQLite的运行环境非常小,如果在编译的时候去掉不需要的功能,可以减小至170KiB,用于嵌入式环境也是没问题的.
- 松散数据类型: 不同于其他数据库的严格的数据类型检查,SQLite在尝试类型转换失败以后,允许在任何表的任何列里面插入任何类型的数据(一个例外是:整型的主键列里面只能存整型数据)
- 变长的数据记录: 任何文本都是VARCHAR
- 可读性很高的源码: 普通的程序员都能读懂,关键的变量和函数都有详细的注释.
- SQL语句编译成虚拟机器语言: SQLite把SQL语句预编译成一种类似机器预言的代码,程序员可以方便得打印出代码及代码的执行结果,这样对debug很有好处.
- 完全的公开: SQLite的源码可以任意下载使用,没有任何约束和版权(一些文档和测试代码是受开源license保护的).
- SQL语言扩展: SQLite可以模块化地添加扩展,以增强其功能
说了这么多特点,那么,SQLite究竟怎么使用呢?
在一般的linux发行版下,安装 sqlite 这个包以后,就可以使用 sqlite3 这个命令来创建和处理数据库文件了.windows/DOS则下载这个文件解压到系统目录,mac则是下载这个文件.
安装完毕以后,就可以用
sqlite3 test.db
这个命令来创建一个空的数据库文件了.
然后,你可以用以下命令来建立一个含有两个列的表:
sqlite3 test.db "create table memos(text, priority INTEGER);"sqlite3 test.db "insert into memos values('deliver project description', 10);" sqlite3 test.db "insert into memos values('lunch with Christine', 100);"
然后可以这样查询出需要的数据:
sqlite3 test.db "select * from memos where priority>20;" lunch with Christine|100
很简单吧~
下面展示一下,SQLite在C语言下的用法,同样用的是上面那个test.db,我们建立一个test.c,内容为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | #include <stdio.h> #include <sqlite3.h> static int callback(void *NotUsed, int argc, char **argv, char **azColName){ int i; for(i=0; i<argc; i++){ printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL"); } printf("\n"); return 0; } int main(int argc, char **argv){ sqlite3 *db; char *zErrMsg = 0; char SQLbuffer[1024]; int rc; if( argc!=2 ){ fprintf(stderr, "Usage: %s num\n", argv[0]); return 1; } rc = sqlite3_open("test.db", &db); if( rc ){ fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db)); sqlite3_close(db); return 1; } sprintf(SQLbuffer, "select * from memos where priority > %s;", argv[1]); rc = sqlite3_exec(db, SQLbuffer, callback, 0, &zErrMsg); if( rc!=SQLITE_OK ){ fprintf(stderr, "SQL error: %s\n", zErrMsg); sqlite3_free(zErrMsg); } sqlite3_close(db); return 0; } |
用
gcc -lsqlite3 test.c
进行编译,完成之后,执行
./a.out 30 text = lunch with Christine priority = 100
怎么样,相当简单吧~
注: 文中部分内容翻译和参考自官方文档和man页.
调srt字幕时间的小脚本
首先,我知道mplayer和很多其他播放都有个类似 -subdelay的开关,可以实现字幕和电影的时间调整。
此脚本和subdelay又部分功能交叉,但是某些特殊的时候,还是用个这个脚本方便。
我当时的是电影一个avi文件,但srt字幕却只找到分CD1和CD2的那种,前半段电影的时间和CD1对上了,但是后半段就没字幕了。
为了解决这个文件,就写了这个脚本,名为 adjsrt.sh
我当时执行了 ./adjsrt.sh 3061 cd2.srt >> cd1.srt 就把第二个字幕的时间整体加上3061秒,然后加在了第一个字幕的后面了,哈哈。
脚本如下:
#!/bin/sh offset=$1 shift awk -v offset=$offset ' BEGIN{ FS="[ :,]+" } /^[0-9][0-9]:[0-9]*/ { ST=toT($1,$2,$3)+offset; ST1=int(ST/3600); ST2=int((ST-ST1*3600)/60); ST3=ST%60; ET=toT($6,$7,$8)+offset; ET1=int(ET/3600); ET2=int((ET-ET1*3600)/60); ET3=ET%60; printf("%02d:%02d:%02d,%03d --> %02d:%02d:%02d,%03d\n", ST1,ST2,ST3,$4,ET1,ET2,ET3,$9); } $0 !~ /^[0-9][0-9]:[0-9]*/ { print $0 } function toT( hour, min , sec ){ return hour*3600 + min*60 + sec } ' $*
python多处理器编程
由于上次做的那个一维随机游走程序,虽然简单,但是大数据的时候很费CPU,而且我注意到我的双核处理器始终只有一核是处于满负荷工作,另一个核的性能没有得到发挥.而且我也试过把同样的程序放到一个8核的服务器上运行,结果解题的速度也只是比我本本快那么一点点,估计也只是那服务器的CPU主频(2GHz)比我的1.86GHz略高而已,完全没有发挥出他8核的优势.
所以马上想到了python有没有多处理机的机制,上网google一下,发现由于python是解释型的语言,而Python解释器使用GIL(全局解释器锁)来在内部禁止并行执行,正是这个GIL限制你在多核处理器上同一时间也只能执行一条字节码指令.猜想这个GIL也是当初为了设计解释器方便而搞的吧.而且据说python 3.0 里面已经改进了,默认有了多处理器编程的库了.但是毕竟现在python3.0还没有流行起来,那么现在有没有变通的方法呢?
当然有~不然我就不会写这文章了嘛~
Parallel Python 这个库,正是为了解决我们的问题而设计的,而且它不仅可以多核处理器协同工作,还可以通过网络集群运行呢,嘿嘿.
下面的中文介绍来自这里:
1 简介
PP 是一个Python模块,提供了在SMP(多CPU或多核)和集群(通过网络连接的多台计算机)上并行执行Python代码的机制。轻量级,易于安装,并集成了其他软件。PP也是一个用纯Python代码实现的跨平台,开放源码模块。
2 功能
* 在SMP和集群上并行执行Python代码
* 易于理解和实现的基于工作的并行机制,便于把穿行应用转换成并行的
* 自动构造最佳配置(默认时工作进程数量等同于系统处理器数量)
* 动态处理器分配(允许运行时改变工作处理器数量)
* 函数的工作缓存(透明的缓存机制确保后续调用降低负载)
* 动态负载均衡(任务被动态的分配到各个处理器上)
* 基于SHA的连接加密认证
* 跨平台移植(Windows/Linux/Unix)
* 开放源代码3 开发动机
现代Python程序已经广泛的应用在商业逻辑,数据分析和科学计算等方面。其中广泛应用着SMP(多处理器或多核)和集群(通过网络连接的多台计算机),市场需要并行的执行的Python代码。
在SMP计算机上编写并行程序最简单的方法是使用多线程。尽管如此,使用 ‘thread’ 和 ‘threading’ 模块仍然无法在字节码一级实现并行。因为Python解释器使用GIL(全局解释器锁)来在内部禁止并行执行。这个GIL限制你在SMP机器上同一时间也只能执行一条字节码指令。
PP 模块正是为了解决这个问题而来,提供简单的方式实现并行Python应用。 ppsmp 在内部使用 进程 和 IPC (进程间通信)来组织并行计算。并处理了所有内部的细节和复杂性,你的应用程序只需要提交工作任务并取回结果就可以了。这也是编写并行程序的最简单的方法。
为了更好的实现,所有使用 PP 的软件通过网络来连接和协作。跨平台和动态负载均衡使得 PP 可以轻松组织多平台、异构的集群计算环境。4 安装
任何平台:下载模块压缩包,解压,运行setup脚本:
python setup.py install
Windows:下载和执行安装包。
另外,debian和ubuntu用户,也可以通过apt直接下载安装,包名是 python-pp ,但是由于版本比较老,是 1.5.4 版本的,而最新的是 1.5.6 ,所以官方页面上的示例代码可能运行不了,会出现以下错误提示:
Traceback (most recent call last):
File “testpp.py”, line 46, in
job_server = pp.Server(ppservers=ppservers)
File “/var/lib/python-support/python2.5/pp.py”, line 312, in __init__
raise ValueError(“secret must be set using command-line option or configuration file”)
ValueError: secret must be set using command-line option or configuration file
原因是代码的不兼容性,解决办法就是找到 pp.Server 那行,多加一个参数,如下:
job_server = pp.Server(ppservers=ppservers,secret="")
由于这个库,包装得不错,所以用起来也比较简单,基本上看了示例代码,就会了,使用方面也就不多介绍了,如果有可能的话,我倒是想写个gentoo的ebuild文件,嘿嘿.
给 iPod 转视频的脚本
由于新买了个 iPod touch,这几天认真钻研了下它的视频格式,搞了个nautilus脚本,使用mencoder做后端.
以后想把某个视频文件转成iPod的格式的话,直接在 nautilus 里面右键点文件-脚本-toIpod 就可以搞定了.
脚本的特点:
* 借助mplayer的强大,支持N多的源格式(已测试: avi rmvb mov flv).
* 支持srt/ass格式的外挂字幕.
* 自动缩放画面比例到适合ipod touch的480*320,如果是 ipod shuffle 之类的话,可以自己修改下脚本.
* 可视化的进度提示
* 转换速度较快
* 默认保存到当前目录,可修改脚本,输出到统一目录,方便管理.会自动加上 _ipod.mp4 的后缀名.
使用方法,保存以下脚本到 ~/.gnome2/nautilus-scripts/toIpod ,并加可执行权限…或者这里下载
PS: 如果压缩出来的字幕有乱码,请参照我以前的文章,建个 ~/.mplayer/mencoder.conf 文件,写上一行 subcp=cp936 就好了.
#!/bin/bash #filename: ~/.gnome2/nautilus-scripts/toIpod #Copyright (c) 2008 bones7456 (bones7456<A>gmail<D>com) #License: GPL #version 20081101 #用于将视频转成 ipod touch / iphone 格式.右击文件使用 SAVEDIR=`pwd` #SAVEDIR="/data/movie" INFILE="$1" PWD=`pwd` CMD="mencoder -of lavf -lavfopts format=mp4 -oac lavc -ovc lavc " CMD+="-lavcopts aglobal=1:vglobal=1:vcodec=mpeg4:vbitrate=600:acodec=libfaac:abitrate=128 " CMD+="-af lavcresample=22050 -vf dsize=480:320:0,scale=0:0,expand=480:320,harddup -ofps 25 -srate 22050 " P="没有找到对应的字幕." if [[ -f "${INFILE%.*}.srt" ]];then CMD+=" -sub ""\"$PWD/${INFILE%.*}.srt\"" P="找到字幕文件: ""${INFILE%.*}.srt" elif [[ -f "${INFILE%.*}.ssa" ]];then CMD+=" -sub ""\"$PWD/${INFILE%.*}.ssa\"" P="找到字幕文件: ""${INFILE%.*}.ssa" elif [[ -f "${INFILE%.*}.aas" ]];then CMD+=" -sub ""\"$PWD/${INFILE%.*}.aas\"" P="找到字幕文件: ""${INFILE%.*}.aas" fi CMD+=" -o ""\"$SAVEDIR/${INFILE%.*}_ipod.mp4\""" ""\"$PWD/$INFILE\"" P+="\n\n保存目录: $SAVEDIR" P+="\n\n是否继续?" #echo "$CMD" >> ~/toIpod.log if ! zenity --question --text "$P" ; then exit 0; fi eval "$CMD 2>&1" |\ while read line; do echo $line |\ awk -F '[ :\(\)%]+' '/^Pos/{print "# 速度:",$5,"(点\"取消\"转入后台运行.)";print $4}' ; done |\ zenity --progress --title "正在转换..." --percentage=0 --auto-close --width=500
截图:

google code jam
玩了下google编程大赛,我那轮3道题目,题目球猫帖这里了,其中的第3,超烦,算什么打苍蝇的概率,算的累死了,为了不让自己的程序白写,贴在这里晒晒,嘿嘿.
PS: 初学python,发现真好用…
- #!/usr/bin/env python
- # -*- encoding: utf-8 -*-
- import math
- def sg(x,R):
- '''求弓形面积'''
- return math.acos(x/R)*(R**2)-x*math.sqrt(R**2-x**2)
- inf=file('C-large.in','r')
- outf=file('C-large.out','w')
- casenum=int(inf.readline())
- for c in range(0,casenum):
- tmp=inf.readline()
- f=float(tmp.split(' ')[0])
- R=float(tmp.split(' ')[1])
- t=float(tmp.split(' ')[2])
- r=float(tmp.split(' ')[3])
- g=float(tmp.split(' ')[4])
- TotalArea=math.pi*R**2/4.0
- A=0
- fn=0
- r=r+f
- t=t+f
- g=g-2*f
- if g > 0:
- i=0
- while i*(g+r*2.0)+r < (R-t):
- x=i*(g+r*2.0)+r
- xp=x+g
- j=0
- Yi=math.sqrt((R-t)**2-x**2)
- try:
- Yip=math.sqrt((R-t)**2-xp**2)
- except:
- Yip=0
- while j*(g+r*2.0)+r 0:
- fn+=nfn
- j+=nfn
- #print "c=",c,"i=",i,"j=",j,nfn
- continue
- if xp < R-t:
- if yp Yip and yp <= Yi:
- if y Yi
- if y < Yip:
- A+=(sg(x,R-t)-sg(xp,R-t))/2.0-g*y
- #w="3a.不规则"
- elif y < Yi:
- A+=(sg(y,R-t)-sg(Yi,R-t))/2.0-(Yi-y)*x
- #w="3b.不规则"
- else: #这个是不可能的
- print "c=",c,"i=",i,"j=",j,"y=",y,"yp=",yp,"Yi=",Yi,"Yip=",Yip,"x=",x,"xp=",xp,"R-t=",R-t #,w
- else:
- if yp <= Yi:
- A+=(sg(y,R-t)-sg(yp,R-t))/2.0-g*x
- #w="4.下不规则"
- else:
- A+=(sg(y,R-t)-sg(Yi,R-t))/2.0-(Yi-y)*x
- #w="5.三角不规则"
- j+=1
- i+=1
- A+=fn*g*g
- #print TotalArea,A
- outf.write('Case #%d: %0.6f\n'%(c+1,(1-A/TotalArea)))
- inf.close()
- outf.close()
C 语言 IQ 题..
http://linuxfire.com.cn/~alecs/fun/xiaoming.txt
小明初学 C 语言,写了个程序,想打印 99 个 ‘#’. 程序如下:
int i, n=99; main() { for(i=0; i<n ; i--) { printf("#"); } }但是这个程序是错的.
Question 1: 请大家帮他改正, 但只允许 1) 删除一个字符 or 2) 增加一个字符 or 3) 改变一个字符
Question 2: 同样的限制条件, 使得只打印一个 ‘#’
Qeustion 3: 同样的限制条件, 打印 100 个 ‘#’
这个题目,粗看无聊,仔细想想还挺有意思的,我归纳了下,有这些答案. 点击查看全文 »
下面要帖答案了,要自己思考下的先别往下看了.