jqka2 发布的文章

linux-programming-note-3(文件i/o操作)

<本笔记基于《LINUX编程技术详解》(人民邮电出版社)>

author:tunpishuang (tunpishuang at gmail dot com)

chapter5-------------文件i/o操作
-----------------------------
open() 打开文件设备
head	<sys/types.h>
	<sys/stat.h>
	<fcntl.h>
define 	int open(const char *pathname,int flags);
	int open(const char *pathname,int flags,mode_t mode);
return	success	file discripter		fail:-1		set errno:yes

flag参数:
O_RDONLY	O_WRONLY	O_RDWR		O_APPEND	O_ASYNC		O_CREAT		
O_DIRECTORY	O_EXCL		O_LARGEFILE	O_NOATIME	O_TRUNC		O_DIRECT

mode参数:
S_IRWXU		S_IRUSR		S_IWUSR		S_IXUSR		
S_IRWXG		S_IRGRP		S_IWGRP		S_IXGRP
S_IRWXO		S_IROTH		S_IWOTH		S_IXOTH

eg:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(void)
{
	int fd1;
	if(fd1=open("openfunctiontest",O_CREAT |O_RDWR,0777)==-1)
	{perror("cannot creat file openfunctiontest");	return 1;}
	close(fd1);
	return 0;
}

---------------------

close() 关闭文件设备 open后必须的操作,否者会造成资源和程序安装的问题。
head	<unistd.h>
define	int close(int fd);
return 	success:o 	fail:-1 	set errno:yes

-----------------------
creat() 创建文件
head 	<sys/types.h>
	<sys/stat.h>
	<fcntl.h>
define 	int creat(const char *pathname,mode_t mode);
return	success:file discripter		fail:-1	set errno:yes

等于int open(const char *pathname,O_CREAT|O_WRONLY|O_TRUNC,mode_t mode);

-----------------------------------

read() 读文件
head	<unistd.h>
define	ssize_t	read(int fd,void *buf,size_t count);
return	suc:读取的字符数,0表示读取到了文件结束位置 	fail:-1		set errno:yes

eg:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(int argc,char *argv[])
{
	int fd;
	char buffer[100];
	int num;
	if(argc!=2) {printf("USage:%s filename\n",argv[0]);  return 1;}
	if((fd=open(argv[1],O_RDONLY))==-1) {perror("cannot open"); return 1;}
	while((num=read(fd,buffer,99))>0)
	{
	buffer[num]='\0';
	printf("%s\n",buffer);
	}
	close(fd);
	return 0;
}
--------------------------------
write() 写文件
head	<unistd.h>
define	ssize_t write(int fd,const void *buf,size_t count);
return	suc:写入字符数,	fail:-1		set errno:yes

eg: 	cp.c
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(int argc,char *argv[])
{
	char buffer[100];
	int fd1,fd2,num;
	if(argc!=3) printf("usage:%s source dest\n",argv[0]);
	if((fd1=open(argv[1],O_RDONLY))==-1) {perror("cannot open\n"); return 1;}
	if((fd2=open(argv[2],O_CREAT|O_WRONLY,0777))==-1) {perror("cannot creat dest\n"); return 1;}

	while((num=read(fd1,buffer,100))>0)
	{				
		write(fd2,buffer,num);	
	}
	close(fd1);
	close(fd2);
	return 0;
}

--------------------------------------------------

lseek() 改变写入文件位置
head	<sys/types.h>
	<unistd.h>
define	off_t lseek(int fildes,off_t offset,int whence);
return	suc:从文件开始位置最后的偏移量 		fail:-1		set errno:yes

offset 偏移量  
whence 文件偏移量的具体计算:
SEEK_SET	SEEK_CUR	SEEK_END

eg:用lseek实现grep功能:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <fcntl.h>
int main(int argc,char * argv[])
{
	int len;
	int fd;
	long offset=0;
	char buffer[1024];
	int flag=0;
	if(argc!=3) {printf("usage: %s \"string\" filename\n"); return 1;}
	len=strlen(argv[1]);
	fd=open(argv[2],O_RDONLY);

	while(1)
	{
		if(lseek(fd,offset,SEEK_SET)==-1) {perror("cannot move the file pointer\n"); return 1;}
		if(read(fd,buffer,len)<len) break;
		buffer[len]='\0';
		if(strcmp(argv[1],buffer)==0) flag++;
		offset++;

	}
	if(flag>0) printf("find the string: %s in file %s %d times\n",argv[1],argv[2],flag);
	close(fd);
	return 0;
}

--------------------------------------

dup() dup2() 输入输出从定向
head	<unistd.h>
define	int dup(int oldfd);
	int dup2(int oldfd,int newfd);
return 	suc:new fd	fail:-1 	set errno:yes
STDIN_FILENO	标准输入,0
STDOUT_FILENO 	标准输入,1
STDERR_FILENO	标准错误,2

eg:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(int argc,char *argv[])
{
	int fd1;
	if(argc!=2) {printf("usage: %s filename\n"); return 1;}
	if((fd1=open(argv[1],O_CREAT|O_RDWR,0777))==-1) {perror("cannot creat\n"); return 1;}
	close(STDOUT_FILENO);
	if(dup(fd1)==-1) {perror("cannot reserved the stdout fd\n"); return 1;}
	printf("write the file\n");
	close(fd1);
	return 0;

}

----------------------------------------如果改为dup2:
dup2(fd1,STDOUT_FILENO);

END

linux-programming-note-2(linux文件和目录)

<本笔记基于《LINUX编程技术详解》(人民邮电出版社)>

author:tunpishuang

chapter4-------------Linux文件和目录

和unix类似,linux不是通过设备标示符来访问文件系统的。
vfs(virtual filesystem):为了屏蔽底层文件系统的实现细节和差异
最早由sun提出,其目的是实现nfs,

getcwd() 获得当前工作目录
head:   <unistd.h>
define: char * getcwd(char *buffer,size_t size)
return: 成功:返回指向当前工作目录字符串的指针 失败:null 设置errno:是
错误信息:
EINVAL
ERANGE
EACCES
eg:
----------------------------------code start
/*getcwd.cxx*/
#include <iostream>
#include <limits.h>
#include <unistd.h>
#ifndef PATH_MAX
#define PATH_MAX 256
#endif
int main(void){

char cur_work_dir[PATH_MAX];
std::cout<<"current max path length is:"<<PATH_MAX<<std::endl;
if(getcwd(cur_work_dir,PATH_MAX)==NULL)
{
 perror("couldn't get cwd!");
 return 1;
}
std::cout<<"current dir is :"<<cur_work_dir<<std::endl;
return 0;
}
---------------------------------code end

pathconf() 获得系统目录最大长度
head <unistd.h>
long pathconf(char *path,int name)
return 成功:返回目录长度极限值 失败:-1  设置errno:是

name可以取值:               错误信息:
_PC_LINK_MAX 		     EINVAL	
_PC_MAX_CANON		     ELOOP	
_PC_NAME_MAX
_PC_PATH_MAX
_PC_CHOWN_RESTRICTED
_PC_NO_TRUNC
_PC_VDISABLE

eg:
/*pathconf.cxx*/
#include <iostream>
#include <unistd.h>
int main(void)
{
	long cur_path_len;
	char* cur_work_dir;
	/*get the max length of the directory*/
	if(cur_path_len=pathconf(".",_PC_PATH_MAX)==-1)
	{perror("couldn't get current working path length"); return 1;}
	std::cout<<"current path length is "<<cur_path_len<<std::endl;
	/*memory allocate according to the length of the dir*/
	if((cur_work_dir=(char *)malloc(cur_path_len))==NULL)
	{perror("couldn't allocate memory for the pathname"); return 1;}
	/*get current working dir*/
	if(getcwd(cur_work_dir,cur_path_len)==NULL)
	{perror("couldn't get current working dir"); return 1;}

	std::cout<<"curren working dir is"<<cur_work_dir<<std::endl;
	return 0;
}
--------------------------------------------------
chdir,fchdir 更改当前工作目录
功能类似cd,
head 	<unistd.h>
define  int chdir(const char* path); 参数是指向目录的字符串指针
	int fchdir(int fd);          参数是目录的文件描述符
return  sucess:0 fail:-1 set errno:yes
error info:
EFAULT
ENAMETOOLONG
ENOENT
ENOMEM
ENOTDIR
EACCES
ELOOP
EIO
EBADF

eg:
-------------------------------code
/*file name: chdir.cxx*/
#include <iostream>
#include <unistd.h>
int main(void)
{
	long cur_path_len;
	char* cur_work_dir;
	/*get the max length of the directory*/
	if(cur_path_len=pathconf(".",_PC_PATH_MAX)==-1)
	{perror("couldn't get current working path length"); return 1;}
	std::cout<<"current path length is "<<cur_path_len<<std::endl;
	/*memory allocate according to the length of the dir*/
	if((cur_work_dir=(char *)malloc(cur_path_len))==NULL)
	{perror("couldn't allocate memory for the pathname"); return 1;}
	/*get current working dir*/
	if(getcwd(cur_work_dir,cur_path_len)==NULL)
	{perror("couldn't get current working dir"); return 1;}

	std::cout<<"curren working dir is"<<cur_work_dir<<std::endl;
	/*chang to dir PARENT directory*/
	if(chdir("..")==-1)
	{perror("couldn't change cwd"); return 1;}
	if(getcwd(cur_work_dir,cur_path_len)==NULL)
	{perror("couldn't et cwd"); return 1;	}
	std::cout<<"after cwd,the cwd is"<<cur_work_dir<<std::endl;
	return 0;
}
-----------------------------
mkdir(),rmdir() 创建,删除目录
head	<sys/stat.h>
	<sys/types.h>
define  int mkdir(const char *pathname,mode_t mode);
return	success:0	fail:-1 set errno:yes
创建目录的权限由mode&~unmask&0777来指定,umask是默认权限,也称为剥夺权限。
error info:
EPERM
EEXIST
EFAULT
EACCES
ENAMETOOLONG
ENOENT
ENOTDIR
ENOMEM
EROFS
ELOP
ENOSPC
ENOSPC

eg:
#include <iostream>
#include <sys/stat.h>
#include <sys/types.h>
int main(void)
{
	char* pathname="/root/program/mkdirtest";
	if(mkdir(pathname,0700)==-1)
	{perror("counldn't mkdir"); return 1;}
	return 0;

}
-------------------------------
rmdir()
head	<unistd.h>
define	int rmdir(const char *pathname);
return 	sucess:0	fail:-1 	set errno:yes
-----------------------------
4.2.2 文件描述符和文件指针
linux为了统一对文件和设备的操作,提供了open,read,close等操作函数,
使用文件描述符来实现对文件的操作。
文件描述符实际上是个整数,man 2 open,read,write,lseek,fcntl

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(void)
{ 
char test;
int fd;
if(fd=open("fd.dat",O_RDONLY)==-1)
{perror("cannot open the fd.dat file"); return 1;}

if(fork()==-1)
{
perror("cannot create the child process");
return 1;
}

/*read the first char in fd.dat file*/
read(fd,&test,1);
printf("process id: %ld read the char :%c\n",(long)getpid(),test);
close(fd);
return 0;
}
--------------------------------------
4.2.3 文件访问权限
4.2.4 stat(),fstat(),lstat()  获取文件信息
head	<sys/types.h>
	<sys/stat.h>
	<unistd.h>
define	int stat(const char *path,struct stat *buf);
	int fstat(int filedes,struct stat *buf);
	int lstat(const char *path,struct stat *buf); 

return	sucess:0	fail:-1		 set errno:yes

几十没有对文件有读取权限,也可以获得文件信息。
lstat和stat一样,除了当path为链接时,获得的将是符号链接的信息,而不是符号链接指向的文件信息.
fstat和stat一样,除了第一个参数时文件描述符。

0x1ff=0777

struct stat {
	dev_t st_dev;
	ino_t st_ino;
	mode_t st_mode;
	nlink_t st_nlink;
	uid_t st_uid;
	gid_t st_gid;
	dev_t st_rdev;
	off_t st_size;
	blksize_t st_blksize;
	blkcnt_t st_blocks;
	time_t	st_atime;
	time_t	st_mtime;
	time_t 	st_ctime;
};

POSIX中定义的检查文件类型的宏说明 
st_mode中定义的相关宏
-----------------------
4.2.5 chmod(),fchmod() 修改文件权限
head	<sys/types.h>
	<sys/stat.h>
define	int chmod(const char *path,mode_t mode);
	int fchmod(int fides,mode_t mode);
return success:0	fail:-1	set errno:yes

chmod fchmod中使用的宏详见man 2 chmod 

-------------------------
4.2.6 chown(),fchown(),lchown() 修改文件属主
head	<sys/types.h>
	<unistd.h>
define	int chown(const char *path,uid_t owner,gidd_t group);
	int fchown(int fd,uid_t owner,gid_t group);
	int lchown(const char *path,uid_t owner,gid_t group);
return	success:0 	fail:-1 set errno:yes
--------------------------

4.2.7 umask()
umask影响新建文件的默认权限,如果umask的值为022,则新创建的文件的权限
为666-022=755 
umask的目的是修改umask的值,以确定程序创建文件的权限,
head	<sys/types.h>
	<unistd.h>
define mode_t umask(mode_t mask);
return success:修改前的umask值, 失败:系统调用总是成功 set errno:no
umask的值一般为S_IWGRP|S_IWOTH (022)

eg:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(void) 
{
	int fd1,fd2;
	fd1=open("test1",O_CREAT|O_RDWR,0777);
	if(fd1<0) {perror("cannot create file test1"); return 1;}
	close(fd1);

	struct stat file_stat;
	if(stat("test1",&file_stat)==-1)
	{perror("cannot get the inf of the test1\n"); return 1;}
	printf("test1 permission is :%o\n",file_stat.st_mode & 0x1ff);

	/*call umask to change the umask value to 077*/
	umask(077);

	if((fd2=open("test2",O_CREAT|O_RDWR,0777))==-1)
	{perror("cannot get the inf of test2 \n"); return 1;}	
	close(fd2);

	if(stat("test2",&file_stat)==-1)
	{perror("cannot get the inf of test2 \n"); return 1;}

	printf("after modification the permission is:%o\n",file_stat.st_mode & 0x1ff);
	return 0;

}

---------------------------------
4.3 硬链接 and 符号链接
创建硬链接ln test test.link,我发现test and test.link具有相通的inode
只有文件可以创建硬链接,不能跨文件系统

软连接:touch link.symbol
	ln -s link.sybol link2

4.3.3 创建,删除链接
link() 创建hard link
head	<unistd.h>
define int link(const char *oldpath,const char *newpath);
return successs:0 fail:-1	set errno:yes

unlink() remove the hard link
head	<unstd.h>
define	int unlink(const char *pathname);
return	success:0	fail:-1 set errno:yes
创建符号链接
symlink()
head	<unistd.h>
int symlink(const char *oldpath,const char *newpath);
return	success:0	fail:-1 set errno:yes

------------------------------------
opendir() 打开参数name指定目录
head	<sys/types.h>
	<dirent.h>
define	DIR *opendir(const char *name);
return	成功:指向dir结构的目录指针	失败:NULL	set errno:yes

readdir 获取打开目录下的具体内容
head	<sys/types.h>
	<dirent.h>
define	 sturct dirent *readdir(DIR *dir);
return 	成功:返回指向dirent结构体的指针  失败:NULL set errno:yes

#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>
int main(void)
{
	DIR* dir;
	struct dirent* drt;
	dir=opendir("/etc/");
	if(dir==NULL) {perror("cannot open the desired dir"); return 1;}

	while((drt=readdir(dir))!=NULL) 
	{printf("filename or dir:%s\n",drt->d_name);}
	closedir(dir);
	return 0;

}
-----------------------------------

实例:ls

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <unistd.h>
#include <dirent.h>
#include <string.h>

	const int N_BITS=3;
	typedef struct dir_lnk{
		char d_name[256];
		struct dir_lnk *next;
		}dirlnk;

	typedef struct item_info{
		unsigned long inode;
		char permission[11];
		int owner;
		int group;
		off_t size;
		time_t mod_time;
		char name[256];
		}info;

	dirlnk* get_dir_detail(char* dirname)
	{
	DIR* dir;
	struct dirent* drt;
	dir=opendir(dirname);
	if(dir==NULL) {perror("cannot open the dir"); return NULL;}
	dirlnk* dir_head=NULL;
	dirlnk* cur_item=NULL;
	dirlnk* next_item=(dirlnk*)malloc(sizeof(dirlnk));
	while((drt=readdir(dir))!=NULL)
		{
		 if(strcmp(drt->d_name,".")||strcmp(drt->d_name,".."));
		 continue;
		}

	if(cur_item=NULL)
	   cur_item=next_item;
	else
	   cur_item->next=next_item;
	   cur_item->next_item;

	if(dir_head=NULL) dir_head=cur_item;
	strcpy(cur_item->d_name,drt->d_name);

	}

	void print_file_info(dirlnk* dir_head)
	{
	 static char* perm[]={"---","-w-","-wx","r--","r-x","rw-","rwx"};
	 unsigned int mask=0700;
	struct stat file_stat;
	dirlnk* cur_dir=dir_head;
	info file_info;
	while(cur_dir!=NULL)
	{
	  mask=0700;
	  if(stat(cur_dir->d_name,&file_stat)==-1)
		{
		  perror("cannot get the info of the file!");
		  cur_dir=cur_dir->next;
		  continue;
		}
	  if(S_ISREG(file_stat.st_mode))  file_info.permission[0]='-';
	  if(S_ISDIR(file_stat.st_mode))  file_info.permission[0]='d';
	 int i=3;
	 int j=0;
	while(i>0)

	file_info.permission[1+j*3]=perm[(file_stat.st_mode & mask)>>(i-1)*N_BITS][0];
	file_info.permission[2+j*3]=perm[(file_stat.st_mode & mask)>>(i-1)*N_BITS][1];
	file_info.permission[3+j*3]=perm[(file_stat.st_mode & mask)>>(i-1)*N_BITS][2];
	j++;
	i--;
	mask>>=N_BITS;
	}	
	 file_info.permission[10]='\0';
	 file_info.owner=file_stat.st_uid;
	 file_info.group=file_stat.st_gid;
	 file_info.mod_time=file_stat.st_atime;
	 file_info.size=file_stat.st_size;
	 strcpy(file_info.name,cur_dir->d_name);
	 file_info.inode=file_stat.st_ino;

	printf("%u ",file_info.inode);
	printf("%s ",file_info.permission);
	printf("%d ",file_info.owner);
	printf("%d ",file_info.group);
	printf("%u ",file_info.size);
	printf("%s ",ctime(&file_info.mod_time));
	printf("%s  \n",file_info.name);

	cur_dir=cur_dir->next;

	}

	int main(int argc, char* argv[])
	{
	 dirlnk* head=get_dir_detail(".");
	 printf_file_info(head);
	}

---------------还有个错误正在sebug

linux-programming-note-1(linux基础,linux开发环境,linux开发工具)

<本笔记基于《LINUX编程技术详解》(人民邮电出版社)>

author:tunpishuang

chapter1 to chapter 3

LSB :linux standard base ,其分支FHS(filesystem hierarchy standard,文件系统分级结构标准)。

Fedora core 支持的体系结构包括x86,x86_64,ppc

Red hat enterprise linux分为advanced server/entry server/workstation/前两个差异再支持内存和CPU大小数量上,
workstation为工作站平台

SUSE分为enterprise desktop(支持X86,X86_64)和enterprise server(支持x86,amd64/emt64t/ppc/ibm power/安腾/ibm zSeries)

vmare--	|vmware esx server,用于大型服务器,包含一个简单LINux,管理硬件,所有OS安装在该LINUX上
	|vmware gsx server 安装在OS上,
	|vmware workstation 和GSX server相似,不带管理工具。

virtual pc(2003 M$收购connectix,删除对非WIN OS的支持)
使用virtual pc安装LINUX? have a try~~

xen
运行在不支持硬件虚拟化的计算机上,必须修改OS内核,因无法修改WINDOWS,3.0版本之前只支持linux.
可以在支持硬件虚拟化的CPU上,在不修改OS kernel的情况下运行。
para-virtualization的采用,xen资源占用是vmware的百分之几。

PAE:Physical Adress extension 物理地址扩展指令集

vmnet0 is bridged to eth0
vmnet8 for NAT
vmnet1 for host-ony
--------------------
bridged networking :客户机和主机再同一个网段内
NAT(网络抵制转换):guest os分配私有IP,vmware实现ip头转换。
Host-only:客户系统与主机系统构成一个私有网络。

有些免费的linux发行版不提供scsi驱动。最好选择ide.
split disk into 2GB files是针对fat32文件系统

id:82 swap
id:83 ext3
mkfs.ext3 /dev/hdb1
mount -t ext3 /dev/hdb1 /mnt/hdb1

root@ubt:/# netstat -an |grep 22  //查看是否开放sshd服务

开放x-window远程访问服务:
/etc/gdm/gdm.conf    
#*#any host 
(xdm==x display manager)
xdm 使用X联盟的X显示管理控制协议,XDMCP,来和X服务器通信 接入端口 177 
[xdmcp]字段中的Enable=True
在windows下用xmanager2连接linux 使用命令/usr/bin/gdm启动gnome桌面管理器

VI:
:1,$s/old/new/g 从文件开口到结尾替换所有old为new
:n,ms/old/new/g  第n行到第m行之间的old替换为new
:s/old/new/g  当前行old替换为new
:X对文件加密 vi -x 解密读取
语法加亮:1:末行模式 syntax on
	  2:/etc/vimrc中去掉syntax on的"(双引号)
:set cindent 设置自动缩进
:se nu 显示行数

Emacs
ctrl+x ctrl+f 文件名:打开文件
ctrl+x ctrl+s保存文件
ctrl+x U:撤销上次一操作
一下写入~/.emacs启用语法高亮
;;启动语法高亮
(global-font-lock-mode t)
(setq font-lock-maximum-decoration t)
;(setq font-lock-support-mode `lazy-lock-mode)

wine的商业版本codeweavers的crossover 支持ms office /lotus notes/ms project/visio /dreamweaver/flash

linux的编程环境构建---------------------vim+ctags+taglist

taglist是vim的源代码浏览插件,功能实现依赖于ctags
http://ctags.sourceforge.net 下载ctags-5.6.tar.gz
http://nchc.dl.sourceforge.net/sourceforge/ctags/ctags-5.7.tar.gz

ctags installation:
tar zxvf ctags-5.6.tar.gz
cd ctags-5.6
./configure
make
./mkinstalldirs
make install

http://vim-taglist.soureforge.net/
http://jaist.dl.sourceforge.net/sourceforge/vim-taglist/taglist_45.zip
taglist installation:
mkdir -p ~/.vim/plugin
mkdir -p ~/.vim/doc
taglist.vim taglist.txt分别放入plugin doc目录
进入vim 命令模式中输入:helptags ~/.vim/doc 
输入Tlist

让ctags和taglist联系起来:
编辑taglist.vim 在if!exists('loaded_taglist')的上面一行加入:
let Tlist_Ctags_Cmd="/usr/local/bin/ctags"

使用vim+taglist+ctags阅读项目代码:
进入项目目录
#ctags -R //对代码建立符号数据库
TlistToggle 切换函数列表开关
ctrl+ww在编辑区和tags区域切换
ctrl+]查看函数的定义 ctrl+o跳回源文件
vim中查看如何安装插件 help add-plugin

------Vim+cscope
Cscope和ctags的区别在于,当代码出现更改是,cscope生成符号数据库的时候,只生成更改的部分,这样速度更快,
http://cscope.sourceforge.net (opensuse自带二进制包)
使用参数:
-R recurse directories for files.
-b build the cross-reference only,只建立符号数据库,不进入cscope
-C Ignore letter case when searching
-c Use only ASCII characters in the cross-ref file (don't compress)
-d Do not update the cross-reference
-h This help screen
-I incdir Look in incdir for any #include files.
-s dir Look in dir for additional source files
-v Be more verbose in line mode.
-V print the version number.
-q:Buid an inverted index for quick symbol searching (cscope.in.ou/cscope.po.out)
-k: Kernel mode -don't use /usr/include for #include files
-i namefile Browse through files listed in namefile,instead of cscope.files
最常用的参数:-Rbkq
用个脚本tag.sh来建立符号数据库
-----------
#!/bin/sh
#查找$1目录下所有.h .c .cc文件
#将文件列表保存到cscope.list
find $1 -name "*.h" -o -name "*.c" -o - name "*.cc" >cscope.list
cscope -Rbkq -i cscope.list
#同时使用ctags建立tags索引
ctags -R
-------------------------------chmod +x, 运行:tag.sh dir
cscope.list 源代码文件列表
cscope.out 符号数据库
cscope.in.out cscope.po.out 为加快索引速度产生的文件

Vim+cscope的使用
vim编译可以加入cscope支持,
:cs show 显示cscope符号数据库连接情况
:cs add /sompath/cscope.out 添加
:cs find 查询函数,变量名称

3.6 源代码阅读工具 slickeidt,
3.7 基于Web的源代码阅读工具:Linux Cross-Reference
3.8 linux c c++编译器
gcc:GNU Compiler Collection
支持的硬件平台:
arm,strongarm,xscale,hitachi sh,Intel i960,x86/IA-32,MIPS,MOtorola ppc,68k,coldfire....------------------

gcc可以编译C,g++用于编译C++
3.8.5 使用gcc控制编译过程
1.预处理 gcc -E -o test.pre.c test.c (preprocess only,don't assemble or link)
2.生成汇编代码 gcc -S test.c (compile only,don't assemble or link)生成test.s
3.生成目标代码 gcc -c test.c (compile and assemble,don't link)生成test.o
4.连接生成最后的可执行代码gcc -o test test.c 

3.9 GNU MAKE
-------------code----------a simple makefile
CC=gcc
CFLAGS=-o
test : test.c
	$(CC) $(CFLAGS) $@ test.c
clean:
	rm test
--------------code end---------

3.9.4 MAKE 工作流程
/*test.part1.c*/
#include <stdio.h>
void part_one()
{printf("in the part one function\n");}

/*test.part2.c*/
#include <stdio.h>
void part_two()
{printf("in the part two function \n");}

/*test.c*/
#include <stdio.h>
extern void part_one();
extern void part_two();
int main(void)
	{
	part_one();
	part_two();
	}
--------------------------所以makefile是这样的:
CC=gcc
CFLAGS=-o
OBJFLAGS=-c
test:test.part1.o test.part2.o test.o
	$(CC) $(CFLAGS) $@ test.o test.part1.o test.part2.o
test.part1.o : test.part1.c
	$(CC) $(OBJFLAGS) test.part1.c
test.part2.o : test.part2.c
	$(CC) $(OBJFLAGS) test.part2.c
test.o : test.c
	$(CC) $(OBJFLAGS) test.c
clean:
	rm test
	rm test.part1.o
	rm test.part2.o
----------------------------------
3.9.5 makefile隐含规则
比如:将后缀为.c的文件编译为.o的文件。
常用以隐含规则:
C程序编译:.o文件自动由同名的.c文件生成,$(CC) -c $(CPPFLAGS)$(CFLAGS)
c++程序编译:.o文件自动由同名的.c/.cc文件生成,$(CXX) -c $(CPPFLAGS)$(CFLAGS)
Pascal程序编译:.o文件自动由同名的.p文件生成,$(PC) -c $(PFLAGS)

3.9.6makefile的模式规则
%.o : %.c
	$(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@

3.10 linux下的调试工具
GDB:
为了让GDB可以获得程序的信息,需要加入参数g:
gcc -o gdb.debug -g gdb.c

file <tab>自动补齐 加载需要调试的程序
run 运行
list 列出具体代码,带有行号 list line_from,line_to(from到to之间显示)
break 设置断点
watch 设置观察变量
next 单步执行 /运行到一个函数内:step:步进
continue 从断点位置继续执行
shell ls -la 不退出gdb执行外部shell
show args 显示运行参数
set args b 设置运行参数
print variable 查看变量
whatis variable 查看变量类型 /ptype 显示数据结构的定义
info break/function 显示当前设置的断点信息/函数信息
delete breakpoint 断点号:删除指定断点号
disable breakpoint 断点号:禁用指定断点号
enable breakpoint ..................
make 不退出gdb编译程序
quit 推出gdb
help 帮助
--------------------------
3.10.5 DDD (data display debugger)
DDD可以做gdb,dbx,wdb,ladebug,jdb,xdb,perl,bash等命令调试工具的图形前端
DDD要求gdb的版本在4.16以上
3.10.8 gdb远程调试
目标板:#gdbserver 192.168.2.1:8888 program 
宿主机:target remote 192.168.2.2:8888

-------------------end of chapter 1 to chapter 3

c problems series 1

1.老师你好,有个C语言问题请教。

#include <stdio.h>
main()
{
union
{
char ch[2];
int d;
}s;
s.d=0x4321;
printf("%x,%x\n",s.ch[0],s.ch[1]);

}

为什么输出21,43 而不是43,21

这个问题不复杂,考到了数据在内存中如何存储问题。数据在内存中存储是从低位到高位,也
就是说先存储的21,在存储的43.所以按序输出时候就输出这个结果了。

2.
%ns和%.ns
从 Planet Chinese Security Community 作者:void@planetchinesesecuritycommunity.org(void)
这段代码有什么问题?

void func(char *p) {
char buf[10+1];
memset(buf,0,sizeof(buf));

// limit string to 10 chars
sprintf(buf,"%10s",p);
printf("Hello, %s\n",buf);
}

答案:
%10s只是用于宽度对齐,超过10字节,仍然全部拷贝,导致溢出.
%.10s才是限制了拷贝长度为10字节

windows xp安装sata硬盘驱动

话说上次给同学去选购笔记本,昨天的昨天他买了Acer 4720Z,5300RMB,朋友买新的机子我当然很高兴,买的时候预装的是vista,我觉得要是你要打游戏,1G的内存还是回去自己装XP算了,不然卡卡卡。事情就是这样同学说游戏卡,叫我给他换个XP,我开始还觉得不就是换个系统啦,无所谓,马上搞定。用了jujumao ghost xp还原gho镜像到c盘,竟然机子还可以启动使用vista ,我一直都不相信是人品问题,还原镜像没有效果就干脆重新用安装个干净的XP,但是如大家的所遇到的问题一样,安装程序找不到机子上面的硬盘。本来XP是2001年的时候出来的,现在也有7年的历史了,所以里面有些现在很常用的驱动没有集成实属正常。我用的是jujumao封装的xp,但是还是没有效果。

老办法

现在买SATA硬盘的人渐渐多了,但是除了几款最新的南桥芯片外,其他南桥芯片接上SATA后在安装系统时都有一个毛病,那就是需要安装额外的驱动,很多初次在SATA上安装操作系统的朋友都发现系统无法认出SATA硬盘,其实那是因为没有安装驱动的缘故。那么额外的驱动要怎么安装呢?很简单,我们要做的只要在系统进入安装选项之前多做一步,下面详细介绍具体的操作。安装过2000/XP的朋友都知道,在进入安装选项界面之前,系统要加载一些驱动等文件,如果你要安装南桥SATA的驱动就要留意了,在加载的时候会有这样的提示提示:

press F6 if you need to install a third party SCSI or RAID driver...

按“F6”.插入你买主板时附送的软盘,里面就有南桥SATA控制器的驱动。什么?你把软盘丢了?!!没问题,你可以去你主板的网站下载,然后把它放到软盘就行了:>(由于文件名因芯片组而异,在这里我们就不具体介绍了)。按“S”安装你自己的驱动。注:有些新的主板可以在安装过程中放入光盘,读取光盘里的驱动,不过大多数还是要用软盘。

新方法

从现在的硬件的行情来看原始的安装方法不好,软驱几本上绝迹了,而且每次安装都要插个软盘肯定是十分麻烦的~~我们按照新的方法来安装就轻松多了,首先,我们改bios里面的sata mode ,不同的主板上面的sata的模式是不一样的,以我同学的acer 4720z为例子。他的笔记本里面的sata模式有ahci (advanced host controller interface ) ,和ide (intergrated device environment),先设置为ide,然后开始安装xp,这样sata硬盘在ide的模式现在工作,所以xp是可以识别的,安装完了后,进入系统手动的在安装sata驱动,重新启动,就ok了。

说了这么多还有很多人不知道ide,sata,ahci的区别,说明如下:

SATA模式是将SATA硬盘映射成IDE模式,这样你用SATA硬盘装系统的时候就不需要装SATA硬盘驱动了
AHCI模式则与SATA模式相反,装系统时需要安装SATA驱动,而且貌似只有这个模式才能打开NCQ功能
RAID模式是要有两块硬盘才能实现的,具体情况可以参照一下网上组建RAID的文章,如果你只有一块硬盘就可以忽略它了

补充:NCQ是一种新的硬盘技术,简单来说开启它之后从一个程序跳到另一个程序时速度会更快,要实现它首先就要在BIOS里选择AHCI模式,然后 在装系统时安装相应的驱动(一般在主板驱动盘里有),安装好系统之后基本上就可以实现了(其实也快不到哪里去,我的硬盘已经打开NCQ了,但是也感觉不出 多快)。