chap 1
1.链接库分为静态链接库.a和共享库.so。
2.静态链接库示例:
hello.c
----------------------------------------
#include
void sayHello(){printf("Hello World!");}
----------------------------------------
静态库.a表示archive(归档)。编译时使用-c阻止编译成完整的程序(因为我们没有定义maind函数)而生成.o文件。然后使用ar归档命令即可生成静态库文件。
a.使用gcc -c hello.c命令编译生成hello.o文件。
b.编写调用sayHello的lib.h文件。
lib.h
----------------------------------------
void sayHello();
----------------------------------------
c.使用ar命令打包静态链接库:ar crv libfoo.a hello.o
d.编写调用程序invoke.c
invoke.c
----------------------------------------
#include
#include "lib.h"
int main(){sayHello();exit(0);}
----------------------------------------
编译命令:gcc -o invoke invoke.c libfoo.a或者gcc -o invoke invoke.c -L. -lfoo(-L.指定库文件目录为当前目录,-lfoo指定调用库文件名为libfoo.a或者libfoo.so)。
e.可以使用nm可以查看函数库、执行程序中调用了哪些函数。
3.静态库的缺点是被多个程序调用时内存库会存在多个相同的副本,从而消耗内存和CPU。动态库可以在内存中保存一份供多个进程同时调用。通过命令ldd可以查看程序需要引用的共享库。
chap 2
1.关于重定向:kill 12345 > err.txt 2 >&1
理解如下:首先将标准输出(1)输出到err.txt,然后将标准错误(2)也输出到err.txt。
2.在shell中,通过$引用变量的值,这样的引用在双引号中会替换为变量的值,而在单引号中不会替换为变量的值。字符串如果包含空格,就要使用双引号引起来。
3.环境变量,$#表示参数的个数,$0表示shell脚本的名字,$$表示进程的pid,$PS1一级提示符号,$IFS分隔符(默认为空格、换行或者制表符)。
4.参数,$1表示第一个参数,$*表示所有参数(各参数之间使用$IFS控制),$@表示所有参数(参数间不使用$IFS分隔,即使$IFS为空也会自动隔开),使用set命令设置参数。
5.条件判断使用布尔值判断命令:test命令或者[(为了增强可读性,同步使用[和],[使用时一定要有空格,结合test命令辅助记忆),例如:
-----------------------------------------
if test -f a.txt
then
...
fi
或者
if [ -f a.txt ]
then
...
fi
-----------------------------------------
常用test命令:=(比较字符串是否相等)、!=(比较字符串不相等)、-n(字符串不为空则真)、-z(字符串为NULL则为真)、-eq/ne/gt/lt/lt/ge(大小判断)、-d(文件夹为真)、-f(文件为真)。
6.控制结构:
a.if
-----------------------------------------
if condition
then statments
else
statments
fi
或者
if condition ; then
statments
else
statments
fi
或者
if condition ; then
statments
elif condition ; then
statments
else
statments
fi
-----------------------------------------
PS:判断字符串时,为了放置引用的变量为空,常加引号引用,采用的格式固定为:if [ "$myvar" = "test" ]
b.for
-----------------------------------------
for variable in values
do
statments
done
-----------------------------------------
c.while
-----------------------------------------
while condition do
statments
done
-----------------------------------------
d.util
-----------------------------------------
util condition do
statments
done
-----------------------------------------
e.case
-----------------------------------------
case varible in
pattern1) statments1 ;;
pattern2) statments2 ;;
*) statments3 ;;
esac
-----------------------------------------
7.函数(如果不使用return,函数执行后返回的是最后一条statment执行的退出码):
-----------------------------------------
function()
{
statements;
return xxx;
}
-----------------------------------------
8.其他命令:.执行命令,break、continue(结构控制语句),:空命令,相当于true的别名,echo-n去掉换行输出显示,exec执行命令,``表达式执行命令(现在常用$(())命令替换),trap用于捕捉信号后执行命令(trapcommand signal),unset取消环境变量或者变量值。
9.grep中使用的正则表达式:^一行开头,$一行的结尾,.任意单个字符,[]包含特定字符([:alnum:]表示字母和数字,[:blank:]空格或者制表符,[:digit:]表示数字,[:alpha:]表示字母)。grep-E表示匹配选项,?表示最多匹配一次,*匹配0次或者多次,+匹配一次或者多次,{n}匹配n次,{n,}匹配n次以上,{n,m}匹配n到m次。例如:grep-E [a-z]\{10\} word.txt表示匹配10个字母。
10.$(command)的结果是command命令的输出。例如:whoishere=$(who)。
11.算数运算:使用``或者$(())。
12.引用变量时,如果需要个其他字符串进行拼接,需要使用{},例如:
-----------------------------------------
for i in 1 2 3
do
echo "the ${i}th one"
done
-----------------------------------------
使用${#param}获取param长度,${param:-bar}设置param默认值为bar。
chap 3
1.底层文件访问:
a.write系统调用:size_t write(int fildes, const char* buf, size_t nbytes),将buf的前nbytes个字节写到文件描述符fildes中,返回写入的字节数,=0表示没有写入任何数据,=-1表示写入失败,错误代码存储在全局变量errno中。
b.read系统调用:size_t write(int fildes, void *buf, size_t nbytes),从fildes关联的文件中读取nbytes个字节到buf中,返回读取到的字节数,=0表示没有读取到任何字节,=-1表示读取失败,错误码记录到errno中。
c.open系统调用:int open(const char *path, int flag,[mode_t mode]),创建一个新的文件描述符,成功返回创建的文件描述符,返回-1表示调用失败,错误码保存在errno中。flag的取值:ORDONLY只读,OWRONLY只写,ORDWR读写,O_APPEND追加,O_TRUNC丢弃原有文件内容,O_CREAT创建文件,O_EXCL如果文件存在open调用失败,防止两个程序同事创建相同的文件。
如果使用O_CREAT,必须使用第三个参数mode。其取值:S_IRUSER文件属主读权限,S_IWUSER文件属主写权限,S_IXUSER文件属主执行权限,S_IRGRP文件属组读权限,S_IROTH其他用于读权限。
文件的访问还取决于umask设置的文件访问掩码。umask的值有三个八进制数字组成,每个数字是数字4、2、1、0(分别表示禁止读、写、执行和都不禁止权限)进行OR的结果,三个数字分别表示用户、组、其他用户对文件的访问权限。
d.close系统调用:int close(intfildes)用于取消文件描述符fildes和文件之间的关联,成功返回0,失败返回-1。
e.lseek系统调用:off_t lseek(int fildes,off_t offset,int whence),该函数调用文件描述符的读写指针位置。offset用于设置偏移,whence用于设置取偏移的方法:SEEK_SET取绝对位置,SEEK_CUR相对于当前位置进行偏移,SEEK_END相对于文件尾的位置进行偏移。函数返回文件开头到指针被设置处的字节偏移量,失败返回-1。
f.fstat/stat/lstat系统调用:用于返回文件的信息到一个buf结构中。
int fstat(int fildes, struct stat* buf)/int stat(const char *path, struct stat *buf)/int lstat(int fildes, struct stat *buf)。fstat通过文件描述符获取文件信息,stat和lstat通过文件路径的方式查看文件的信息,但当文件路径指向的是一个符号链接是,lstat返回的是符合的内容,stat返回的是符号链接执行的内容。stat结构的内容包括文件的类型、nodeid、上次修改时间等。
g.dup和dup2系统调用,用于复制文件描述符,可用于使用多个文件描述符操作同一个文件,从而在文件不同的位置操作文件。
int dup(int fildes)复制文件描述符,返回一个新的文件描述符;
int dup(int fildes1, int fildes2)复制fildes1到fields2。
2.标准I/O库,带缓冲区,默认打开三个文件流:stdin、stdout、stderr。
a.FILE *fopen(const char *filename,const char *mode):打开由filename指定的文件,打开的方式由mode指定(r/rb,w/wb,a/ab,r/r+b[更新方式,读和写,a表示以二进制而不是文本模式],w/w+b,a/a+b)),成功返回飞空FILE指针,失败返回NULL。
b.size_t fread(void *ptr,size_t size,size_t ntimes,FILE *stream)用于读取stream文件流到ptr指定的缓存去中,size用于指定读取读取文件记录的长度,ntimes用于记录读取文件记录的次数,返回值是读取文件记录的次数,而不是读取到的字节数。当读取到文件尾时,其返回值可能小于ntimes。
c.FILE *fwrite(void *ptr,size_t size,size_t ntimes,FILE *stream)用于将ptr指向的缓存区中的内容写入到stream流打开的文件中,size表示写入文件记录的大小,ntimes表示写入的次数,函数返回成功写入的次数。
d.int fclose(FILE *stream)关闭stream流,将缓存区中的数据都写出(隐含调用fflush)。
e.int fflush(FILE *stream)将当前缓冲区中的内容立即写出。
f.int fseek(FILE *stream, long int offset, int whence)为下一次操作指定读写位置。
g.int fget(FILE *stream)/int getc(FILE *stream)/int getchar()从stream中读取一个字符并将其返回,getc从stdin中读取。返回int类型,因此不要用char接收。
h.int fputc(int c,FILE *stream)/int putc(int c,FILE *stream)/int putc(int c)将字符c写入到流或者stdout,返回写入的字符。
i.int printf(const char *format,...)/int sprintf(char *s, const char *format,...)/int fprintf(FILE *file, const char *format,...)
其中,printf输出到标准输出,sprintf输出到字符和null空字符输出到s中,fprintf将内容写入到文件流file中。
j.int scanf(const char *format,...)/int fscanf(FILE *file,const char *format,...)/int sscanf(char *s,const char *format,...)
scanf读取标准输入到对应的变量中,fscanf读取文件中的内容到对应的变量中,sscanf读取s中的内容到对应的变量中。
k.fgetpos获取文件流中当前读写位置,fsetpos设置文件流中当前读写位置,ftell返回文件当前读写位置偏移量,rewind重置文件文件流的读写位置,freopen重新使用一个文件流,setvbuf设置文件流的缓存机制,remove相当于unlink,如果参数是个目录,相当于rmdir,feof用于检查文件是否到达文件尾部。
l.chmod改变文件、目录的权限,chown设置文件属主,unlink删除一个文件并减少其链接数,link创建一个指向已有文件的链接,syslink创建符号链接,mkdir创建目录,rmdir删除目录,chdir改变目录,getcwd确定当前目录。
m.opendir打开目录返回DIR结构,readdir读取DIR结构,telldir返回当前目录流的位置,seekdir设置目录流中指针位置,closedir关闭目录流。
n.char *strerror(int error)j将错误代码映射成一个字符串。void perror(const char *str)将错误代码映射成字符串并输出到标准输出。字符的前面加上冒号和空格。例如:perror("Remind")可能输出:Remind: Too many open files
3./proc文件存储系统的信息。如/proc/version显示内核版本,/proc/meminfo显示内存使用情况。
4.关于内存映射函数mmap。mmap允许不同程序共享同一块内存。mmap创建一个指向一段内存区域的指针,该内存区域与可以通过一个打开的文件描述符访问的文件相关联。
void *mmap(void *addr,size_t len,int prot,int flags,int fildes,off_t off)
addr可访问内存地址,len表示可以访问的内存长度,prot用于设置内存访问权限(PROT_READ/WRITE/EXEC),flags用于设置修改内存对于程序的影响(MAP_PRIVATE:对内存的修改只对本进程有效,MAP_SHARED:对内存段的修改记录到文件中),fildes用于指定文件描述符,off用于设置访问内存映射访问偏移。
int msync(void *addr,size_t len,int flags)将内存段的修改写入到文件中。
int munmap(void *addr,size_t len)释放内存段。