正在加载...

备忘 startx执行过程

六月 7th, 2011

2011-5-1的记录。由于跨墙工具失效,当时没传上来,后来就忘了。今日补上。

 

重温关于x-window中x、wm的关系
X 是协议
xinit 启动图形界面但不启动wm ,也就是说只启动了x server(也叫显示管理器)而没有启动x client(比如wm) 。
twm、gnome-session 和 startkde 都属于wm(窗口管理器) 。
kde (KING DESKTOP ENVIRMENT),gnome(GNU Network Object Model Envirment)不只是wm,还包含了配套的应用软件和桌面环境比如任务栏/开始菜单/桌面图标等等,因此是图形界面操作环境。

 

gnome启动过程分析:
1) /usr/bin/startx 确定 x server 和 x client 的配置文件路径和程序
默认为:
userclientrc=$HOME/.xinitrc # 用户指定的 x client 配置脚本,优先级高
sysclientrc=/etc/X11/xinit/xinitrc # 系统的 x client 配置脚本
userserverrc=$HOME/.xserverrc # 用户指定的 x server 配置脚本,优先级高
sysserverrc=/etc/X11/xinit/xserverrc # 默认的 x server 配置脚本
defaultclient=/usr/bin/xterm # 系统默认的 x client 程序
defaultserver=/usr/bin/X # 系统默认的 x server 程序

最后以确定的 x server/client 程序/选项为参数调用xinit

2) /usr/bin/xinit 根据传过来的 x server/client 或选项脚本启动x server 和 x client

3) 在 /etc/X11/xinit/xinitrc(只简单执行 /etc/X11/Xsession) 中启动 x client 也就是 gnome-session
 /etc/X11/Xsession 中主要是依次执行 SYSSESSIONDIR 中的启动脚本

 默认:
SYSSESSIONDIR=/etc/X11/Xsession.d # 默认的 session 文件目录
USERXSESSION=$HOME/.xsession # 默认的用户session 文件目录
USERXSESSIONRC=$HOME/.xsessionrc # 默认的用户session配置文件
 
也就是说,/etc/X11/Xsession.d/ 下面的脚本将被顺序执行(运行 run-parts --list /etc/X11/Xsession.d/ 可以列出这些脚本)

kevin@localhost:/etc/X11$ run-parts --list /etc/X11/Xsession.d/
/etc/X11/Xsession.d//00_handle_guest_session
/etc/X11/Xsession.d//10fglrx
/etc/X11/Xsession.d//20x11-common_process-args
/etc/X11/Xsession.d//30x11-common_xresources
/etc/X11/Xsession.d//40x11-common_xsessionrc
/etc/X11/Xsession.d//50x11-common_determine-startup
/etc/X11/Xsession.d//52libcanberra-gtk-module_add-to-gtk-modules
/etc/X11/Xsession.d//55gnome-session_gnomerc
/etc/X11/Xsession.d//60x11-common_localhost
/etc/X11/Xsession.d//60xdg-user-dirs-update
/etc/X11/Xsession.d//60xdg_path-on-session
/etc/X11/Xsession.d//65compiz_profile-on-session
/etc/X11/Xsession.d//70gconfd_path-on-session
/etc/X11/Xsession.d//75dbus_dbus-launch
/etc/X11/Xsession.d//80appmenu
/etc/X11/Xsession.d//80im-switch
/etc/X11/Xsession.d//90consolekit
/etc/X11/Xsession.d//90x11-common_ssh-agent
/etc/X11/Xsession.d//99x11-common_start
kevin@localhost:/etc/X11$ cat /etc/X11/Xsession.d//50x11-common_determine-startup
# $Id: 50x11-common_determine-startup 305 2005-07-03 18:51:43Z dnusinow $

# This file is sourced by Xsession(5), not executed.

# If no X session startup program was passed to the Xsession script as an
# argument (e.g., by the display manager), or if that program was not
# executable, fall back to looking for a user's custom X session script, if
# allowed by the options file.
if [ -z "$STARTUP" ]; then
  if has_option allow-user-xsession; then
    for STARTUPFILE in "$USERXSESSION" "$ALTUSERXSESSION"; do
      if [ -e "$STARTUPFILE" ]; then
        if [ -x "$STARTUPFILE" ]; then
          STARTUP="$STARTUPFILE"
        else
          shell=${SHELL:-sh}
          STARTUP="$shell $STARTUPFILE"
        fi
        break
      fi
    done
  fi
fi

# If there is still nothing to use for a startup program, try the system
# default session manager, window manager, and terminal emulator.
if [ -z "$STARTUP" ]; then
  if [ -x /usr/bin/x-session-manager ]; then
    STARTUP=x-session-manager
  elif [ -x /usr/bin/x-window-manager ]; then
    STARTUP=x-window-manager
  elif [ -x /usr/bin/x-terminal-emulator ]; then
    STARTUP=x-terminal-emulator
  fi
fi

# If we still have not found a startup program, give up.
if [ -z "$STARTUP" ]; then
  ERRMSG="unable to start X session ---"
  if has_option allow-user-xsession; then
    ERRMSG="$ERRMSG no \"$USERXSESSION\" file, no \"$ALTUSERXSESSION\" file,"
  fi
  errormsg "$ERRMSG no session managers, no window managers, and no terminal" \
           "emulators found; aborting."
fi

# vim:set ai et sts=2 sw=2 tw=80:
kevin@localhost:/etc/X11$

在上面脚本/etc/X11/Xsession.d//50x11-common_determine-startup里 /usr/bin/x-session-manager /usr/bin/x-window-manager /usr/bin/x-terminal-emulator 依次被检查是否存在,第一个存在的将被确定为STARTUP:
kevin@localhost:/etc/X11$ ll /usr/bin/x-session-manager
lrwxrwxrwx 1 root root 35 2011-02-11 05:23 /usr/bin/x-session-manager -> /etc/alternatives/x-session-manager*
kevin@localhost:/etc/X11$ ll /etc/alternatives/x-session-manager
lrwxrwxrwx 1 root root 22 2011-02-11 05:23 /etc/alternatives/x-session-manager -> /usr/bin/gnome-session*
kevin@localhost:/etc/X11$


kevin@localhost:/etc/X11$ cat /etc/X11/Xsession.d//99x11-common_start
# $Id: 99x11-common_start 305 2005-07-03 18:51:43Z dnusinow $

# This file is sourced by Xsession(5), not executed.

exec $STARTUP

# vim:set ai et sts=2 sw=2 tw=80:
kevin@localhost:/etc/X11$

可见脚本/etc/X11/Xsession.d//99x11-common_start 中,STARTUP 也就是 gnome-session 最终被执行。

最简单的自定义x server/client:
在~/.xserverrc 里写入/usr/bin/X11/X :1
在~/.xinitrc 里写入/usr/bin/X11/xeyes -display localhost:1
这就是最简单的X server + X client了,只不过把屏幕编号从默认的0改为了1 。

备忘 wikipedia api 的简单使用

六月 7th, 2011
wikipedia api (..More)

python 调用 ICTCLAS2011

四月 13th, 2011

基本上就是两种方式

1)直接调用。这是通过ctypes完成的,注意linux下的libICTCLAS50.so的导出函数名需要通过nm得到。

 

from ctypes import cdll,create_string_buffer,addressof,c_char_p,string_at
ld=cdll.LoadLibrary('/home/kevin/proj/ICTCLAS50_Linux_RHAS_32_C/API/libICTCLAS50.so')
Init=getattr(ld,'_Z12ICTCLAS_InitPKc')
Init('/home/kevin/proj/ICTCLAS50_Linux_RHAS_32_C/API/')
ImportDict=getattr(ld,'_Z22ICTCLAS_ImportUserDictPKci9eCodeType')
Process=getattr(ld,'_Z24ICTCLAS_ParagraphProcessPKciPc9eCodeTypeb')
Exit=getattr(ld,'_Z12ICTCLAS_Exitv')

print 'before:'
szText = '如果你增加了一些成员变量, 全能补全还不能马上将新成员补全, 需要你重新生成一下tags文件, 但是你不用重启vim, 只是重新生成一下tags文件就行了, 这时全能补全已经可以自动补全了, 还真够"全能"吧'
cntText=len(szText)
buf=create_string_buffer(cntText*6)
rlen=Process(szText,cntText,buf,3,False)
print buf.value

usrDict='成员变量@@nr;新成员@@nr;补全@@nr;重启@@nr'
rlen=ImportDict(usrDict,len(usrDict),1)
print '%d imported.'%rlen

print 'after:'
rlen=Process(szText,cntText,buf,3,False)
print buf.value
Exit()

2)通过二次封装,做一个python的扩展模块,这样就可以通过 import 这个模块直接使用了,简化了参数转换的过程。

 

 

sys.path.append(os.path.expanduser('~/.codeblocks/myProj/ictclas5/'))
import ictclas5_wrapper as ic
ret=ic.Init(os.path.expanduser('~/proj/ICTCLAS50_Linux_RHAS_32_C/API/'))
if not ret:
	print 'init error, check ictclas.log for details!'
	sys.exit()
ic.SetPOSmap(ic.POSMAP.ICT_POS_MAP_SECOND)
szText = '如果你增加了一些成员变量, 全能补全还不能马上将新成员补全, 需要你重新生成一下tags文件, 但是你不用重启vim, 只是重新生成一下tags文件就行了, 这时全能补全已经可以自动补全了, 还真够"全能"吧'
cntText=len(szText)
rslt=' '*cntText*6
retlen=ic.ParagraphProcess(szText,cntText,rslt,ic.CODETYPE.CODE_TYPE_UTF8,False)
print rslt[:retlen]

usrDict='成员变量;新成员;补全;重启'
ret=ic.ImportUserDict(usrDict,len(usrDict),ic.CODETYPE.CODE_TYPE_ASCII)
print '%d imported'%ret

retlen=ic.ParagraphProcess(szText,cntText,rslt,ic.CODETYPE.CODE_TYPE_UTF8,False)
print rslt[:retlen]

ic.SaveTheUsrDic()
ic.Exit()

 

 

写python扩展用boost.python比较方便,ubuntu下apt-get install libboost-python-dev 后就可以开始写了:

 

 

#ifndef OS_LINUX
#define OS_LINUX
#endif
#include <boost/python.hpp>
#include <boost/python/list.hpp>
#include <string>
#include "ICTCLAS50.h"

using namespace boost::python;
using namespace std;

enum POSMAP{
	ENUM_ICT_POS_MAP_SECOND = ICT_POS_MAP_SECOND, \
  ENUM_ICT_POS_MAP_FIRST = ICT_POS_MAP_FIRST, \
  ENUM_PKU_POS_MAP_SECOND = PKU_POS_MAP_SECOND, \
  ENUM_PKU_POS_MAP_FIRST = PKU_POS_MAP_FIRST, \
  ENUM_POS_MAP_NUMBER = POS_MAP_NUMBER};

enum CODETYPE{
	ENUM_CODE_TYPE_UNKNOWN = CODE_TYPE_UNKNOWN, \
	ENUM_CODE_TYPE_ASCII = CODE_TYPE_ASCII, \
	ENUM_CODE_TYPE_GB =	CODE_TYPE_GB, \
	ENUM_CODE_TYPE_UTF8 = CODE_TYPE_UTF8, \
	ENUM_CODE_TYPE_BIG5 = CODE_TYPE_BIG5};

struct my_result{
  int iStartPos; //开始位置
  int iLength; //长度
  char szPOS[POS_SIZE];//词性
  int	iPOS; //词性ID
  int iWordID; //词ID
  int iWordType; //词语类型,用户词汇?(0-否,1-是)
  int iWeight;// 词语权重
};

my_result& copy_result_t(my_result& re, const tagICTCLAS_Result& t)
{
	re.iStartPos = t.iStartPos;
	re.iLength = t.iLength;
	strcpy(re.szPOS, t.szPOS);
	re.iPOS = t.iPOS;
	re.iWordID = t.iWordID;
	re.iWordType = t.iWordType;
	re.iWeight = t.iWeight;
	return re;
}


//LPICTCLAS_RESULT ParagraphProcessA(
//	const char*  pszText,
//	int			    iLength,
//	int			    &nResultCount, //[out]
//	eCodeType	codeType=CODE_TYPE_UNKNOWN,
//	bool		        bEnablePOS=false)
//{
//	return ICTCLAS_ParagraphProcessA(pszText,iLength,nResultCount,codeType,bEnablePOS);
//}
list ParagraphProcessA(
	const char*  pszText,
	int			    iLength,
	int			    &nResultCount, //[out]
	CODETYPE	codeType=ENUM_CODE_TYPE_UNKNOWN,
	bool		        bEnablePOS=false)
{
	const LPICTCLAS_RESULT re = ICTCLAS_ParagraphProcessA(pszText, iLength, nResultCount, eCodeType(codeType), bEnablePOS);
	list result;
	for (int i=0; i<nResultCount; i++)
	{
		my_result my_rslt;
		my_rslt = copy_result_t(my_rslt, re[i]);
		result.append(my_rslt);
	}
	return result;
}


bool Init(const char* pszInitDir=NULL)
{
	return ICTCLAS_Init(pszInitDir);
}


bool Exit()
{
	return ICTCLAS_Exit();
}

bool SetPOSmap(int nPOSmap)
{
	return ICTCLAS_SetPOSmap(nPOSmap);
}


unsigned int ImportUserDictFile(
	const char* pszFileName,
	CODETYPE codeType=ENUM_CODE_TYPE_UNKNOWN)
{
	return ICTCLAS_ImportUserDictFile(pszFileName,eCodeType(codeType));
}


unsigned int ImportUserDict(
	const char* pszDictBuffer,
	const int nLength,
	CODETYPE codeType=ENUM_CODE_TYPE_UNKNOWN)
{
	return ICTCLAS_ImportUserDict(pszDictBuffer,nLength,eCodeType(codeType));
}


int SaveTheUsrDic()
{
	return ICTCLAS_SaveTheUsrDic();
}


int ParagraphProcess(
	const char*  pszText,
	int			    iLength,
	char*		    pszResult, //[out]
	CODETYPE	codeType=ENUM_CODE_TYPE_UNKNOWN,
	bool		        bEnablePOS=false)
{
	return ICTCLAS_ParagraphProcess(pszText,iLength,pszResult,eCodeType(codeType),bEnablePOS);
}




bool ResultFree(LPICTCLAS_RESULT pRetVec)
{
	return ICTCLAS_ResultFree(pRetVec);
}


bool FileProcess(
	const char* pszSrcFileName,
	const char* pszDstFileName,
	CODETYPE	srcCodeType=ENUM_CODE_TYPE_UNKNOWN,
	bool		        bEnablePOS=false)
{
	return ICTCLAS_FileProcess(pszSrcFileName,pszDstFileName,eCodeType(srcCodeType),bEnablePOS);
}

/*
int ParagraphProcessAW(
	const char*               pszText,
	LPICTCLAS_RESULT  pResult,
	CODETYPE	             codeType=ENUM_CODE_TYPE_UNKNOWN,
	bool	  	                     bEnablePOS=false)
{
	return ICTCLAS_ParagraphProcessAW(pszText,pResult,eCodeType(codeType),bEnablePOS);
}
*/

int test(const char* pszText,int cnt, char *rslt,CODETYPE ct)
{
	strcpy(rslt,"ok?");

}

BOOST_PYTHON_MODULE(ictclas5_wrapper)
{
	class_<my_result>("tagICTCLAS_Result")
  .def_readonly("iStartPos", &my_result::iStartPos)
  .def_readonly("iLength", &my_result::iLength)
  .def_readonly("szPOS", &my_result::szPOS)
  .def_readonly("iPOS", &my_result::iPOS)
  .def_readonly("iWordID", &my_result::iWordID)
  .def_readonly("iWordType", &my_result::iWordType)
  .def_readonly("iWeight", &my_result::iWeight);

	enum_<POSMAP>("POSMAP")
  .value("ICT_POS_MAP_SECOND", ENUM_ICT_POS_MAP_SECOND)
  .value("ICT_POS_MAP_FIRST", ENUM_ICT_POS_MAP_FIRST)
  .value("PKU_POS_MAP_SECOND", ENUM_PKU_POS_MAP_SECOND)
  .value("PKU_POS_MAP_FIRST", ENUM_PKU_POS_MAP_FIRST)
  .value("POS_MAP_NUMBER", ENUM_POS_MAP_NUMBER);

	enum_<CODETYPE>("CODETYPE")
	.value("CODE_TYPE_UNKNOWN", ENUM_CODE_TYPE_UNKNOWN)
	.value("CODE_TYPE_ASCII", ENUM_CODE_TYPE_ASCII)
	.value("CODE_TYPE_GB", ENUM_CODE_TYPE_GB)
	.value("CODE_TYPE_UTF8", ENUM_CODE_TYPE_UTF8)
	.value("CODE_TYPE_BIG5", ENUM_CODE_TYPE_BIG5);

	def("Init", Init);
	def("Exit", Exit);
	def("SetPOSmap", SetPOSmap);
	def("ImportUserDictFile", ImportUserDictFile);
	def("ImportUserDict", ImportUserDict);
	def("SaveTheUsrDic", SaveTheUsrDic);
	def("ParagraphProcess", ParagraphProcess);
	def("ParagraphProcessA", ParagraphProcessA);
	def("ResultFree", ResultFree);
	def("FileProcess", FileProcess);
//	def("ParagraphProcessAW", ParagraphProcessAW);

	def("test", test);
}

 

 

编译可以不用bjam,那个比较麻烦,直接写个Makefile:

 

 

all:
	        gcc main.cpp -shared -fPIC -o ictclas5_wrapper.so -I/usr/include/python2.6 -I/home/kevin/proj/ICTCLAS50_Linux_RHAS_32_C/API -lboost_python -L/home/kevin/proj/ICTCLAS50_Linux_RHAS_32_C/API -lICTCLAS50 -m32 -DOS_LINUX
clean:
	        rm ictclas5_wrapper.so

 

到时候直接makefile就可以了,只要路径别写错就没别的需要注意的了。

 

另外使用 ICTCLAS_ImportUserDict时,要注意eCodeType,如果和传过去的pszDictBuffer的类型不匹配,会导致用户自定义词组import错误或者不完全,无法用于分词中。

ubuntu 10.10下login screen中登陆跳回问题

三月 29th, 2011

今天遇到了个关于ubuntu 10.10登陆奇怪的问题:

我用的是desktop版,在正常情况下通过图形界面(login screen)输入用户名密码登陆后就会进入桌面,而今天输入后屏幕黑了一下就又回到登陆界面了,而选择ctrl+alt+1开文本界面,顺利登陆后执行startx,提示startx已经在运行(/tmp/.X0-lock存在);无奈只好重启,在grub界面选择recovery模式,显示字符界面的选择列表后选第一个resume normal boot,登陆后执行startx则顺利进入gnome的图形界面。但是此后如果在ctrl+alt+1和ctrl+alt+7两者之间反复切换,可能会使ctrl+alt+7下的图形界面黑屏(但能看到鼠标),此时只能重启了。

从现象上看好像是通过图形界面启动startx时会出错,自己在recovery mode的resume normal boot中启就没问题,这方面没研究过因此不知道如何解决,现在只好先这么用着了。。。

chrome的插件proxy switchy影响wingide?

三月 14th, 2011

今天调试python自编的一个爬论坛程序是碰到一个很诡异的问题:在shell里面用 python xxx.py执行脚本没有问题,而在wing ide中执行debug时则会返回URLError 连接被拒绝。最后debug到/usr/lib/python2.6/urllib.py的getproxies_environment()中才真相大白:python脚本中并没有设置proxy,但是默认的ProxyHandler调用函数从os.environ中取到了一个变量'http_proxy',并将其对应的值(一个ip地址)做为了http请求使用的proxy。这个ip是127.0.0.0:8580,如此熟悉让俺立即想到一种可能,经过测试,原来是昨天使用浏览器chrome,将里面的插件proxy switchy设置为使用某个proxy(你懂的)后没有取消就退出了,导致wingide能取到这个值。但是奇怪在在shell里面执行python,从os.environ()中却找不到这个值,只有在wing ide中debug/execute脚本时,其os.environ中才有,有兴趣的同学可以找找原因,到底wing ide做了啥额外的操作取得了这个变量,或者说proxy switchy!将此proxy设置保存到了哪里?

 

环境:ubuntu 10.0,chrome 9.0.597.107 (75357) ,Proxy Switchy! 1.6.3,wingide 3.2.12-1,python 2.6.6

复现方法:

1)在chrome中安装Proxy Switchy!,设置一个proxy(任意设置一个ip:port,比如127.0.0.1:8888)并enable它,使chrome使用此proxy访问网页;

2)在wingide中新建脚本:

#coding=utf-8

import cookielib, urllib2
cj = cookielib.CookieJar()
opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cj))
urllib2.install_opener(opener)
req=urllib2.Request("http://www.google.com")

3)在wingide的project中debug/execute此脚本,会发现无法连接,下breakpoint在urllib.py的getproxies_environment()中的此行:

proxies[name[:-6]] = value;

可以看到取到了一个变量http_proxy,其值就是你设置的那个proxy的ip:port;

4)在shell中直接执行此脚本,则可以连接;

5)在chrome中切换proxy switchy!到Direct Connection,再次执行3)和4),会发现可以连接了,不再取到变量 http_proxy。

 

 


google reader 抓虾
bloglines my yahoo
哪吒 鲜果
* 更多订阅本站方式请看 订阅帮助