一、入门

查看linux的环境变量 echo $PATH
使用冒号进行分割PATH变量里面的条目,而不是windows里使用分号。

gcc -o exename codename.cpp 通过编译codename.cpp生成一个exename的应用程序
如果不写-o exename这个参数,则生成的应用程序为a.out
包含头文件 -I头文件目录
包含lib库 -L库目录 -l库名称

库名以lib开头,但是使用的时候未必是这个库的名字名。
比如libcurlXXX.xxx那么在包含的时候写-lcurl
.o 目标文件,一般是程序编译后的二进制文件,相当于VC的obj文件。
使用-c参数生成,一个代码文件生成一个对应的目标文件。
.a 代表静态函数库,相当于VC的lib文件。
静态库也称作归档文件(archive),可以通过ar和ranlib来生成。
ar命令可以把一个个目标文件添加到静态库文件的末尾去。
ranlib命令来对静态库的符号索引表进行更新。
.so 代表恭喜函数库,相当于VC的dll文件。

我主要使用kdevelop作为开发工具,真正直接使用gcc并不多。

二、shell程序设计

我们正常使用的都是/bin/bash这个shell
/bin/sh是一个link文件,链接到/bin/bash。

P17页的set -C 相当于 set -o noclobber 作用是不能覆盖文件了,如果覆盖文件,会出现“cannot overwrite existing file”的提示,并终止。
如果要恢复,则使用set +o noclobber恢复正常状态。

>可以将屏幕输入覆盖到文件,比如ll>123.txt
>>可以将屏幕输入追加到文件,比如ps>123.txt
<可以将文件内容输入给程序,比如more<123.txt 以more的形式在屏幕上输出。
2>可以将错误信息输入覆盖到文件,比如kill 9999999 2>123.err 此时如果使用>,那么文件会为空。
2>>可以将错误信息输入追加到文件。
如果要把标准输出和错误输出到同一个文件,要2>&1 比如 kill 9999999 >123.txt 2>&1
如果要丢弃输入,即不显示屏幕也不保存,可以写入回收站(/dev/null)比如 kill 9999999 >/dev/null 2>&1

| 即管道,可以实现多个命令同时运行,而且数据流在它们之间的传递可以自动进行协调。

脚本里如果运行程序,那么这是一个阻塞的过程,只有这个程序运行结束,才会执行下一条脚本语句。如果只是启动程序后要继续脚本操作,可以加上&参数后台运行。
(顺便说一下,如果执行应用程序给于参数是&,那么在main函数里获得的参数里是没有&这个参数的,如果&在中间,那么后面的参数全部无效,argc的参数数量也只记录&前面的参数。linux里获得的第一个参数和windows一样,都是应用程序的执行路径。区别是windows是绝对路径,linux只是启动命令,如"./test.exe")

以前一直以为./是执行应用程序用的命令,现在才知道./是把程序的完整路径告诉shell来执行,如果想不用./来执行应用程序,那么需要把该程序目录添加到$环境变量中去。

$for file * 可以显示当前目录文件的文件名和编码格式。

脚本的规则很烦人,对空格要求很严格,有时候多个空格不行,有时候少个空格也不行。
不能随便加空格,否则出错:
a1="123" #yes
a1空格="123" #error
a1=空格"123" #a1为空

有的地方空格必须加,否则出错:
if [ "$SHELL" = "/bin/bash" ];then
if [空格"$SHELL" = "/bin/bash"空格];then

[ -f "1.txt" ]&&{ echo '& yes';exit 1;}
[空格-f "1.txt"空格]&&{空格echo '& yes';exit 1;}分号必须加


特殊变量$# 表示包含自定义参数的个数,如果没有自定义参数则为0
$0表示脚本的名字(其实不准确,应该是启动这个脚本的命令,如"./test.sh" 。如果使用完整路径启动,那么就是具体的路径名+脚本名),不算在$#中。
$1表示传入的第一个参数。
$$这个脚本的进程号。

具体if指令见P27页,不能用大于小于号很让人郁闷。
if中的变量如果要进行比较,都要加上""双引号。

其他的用到再查书吧。

三、文件操作

linux几乎一切都是文件,可以用文件打开的方式使用网络连接,串行口等其它设备。

0 标准输入
1标准输出
2标准错误
可以使用write(1,"",n)或者write(2,"",n) ,read(0,buf,n)

size_t是无符号整型

read的第三个参数如果大于实际字符串长度,那么会把内存中的其它值一起读出来。

open返回的文件描述符是唯一的,如果2个程序打开同一个文件,那么会得到2个不同文件描述符,他们的写位置是相互独立的,会导致彼此覆盖。
3个必须制定的访问模式O_RDONLY,OWRONLY,O_RDWR ,如果都不写,则默认O_RDONLY 。
O_APPEND(追加写入,这个是默认的),O_TRUNC(打开时设置文件为空),O_CREAT(按照第三个参数创造文件,如果不给参数,则没有写入的权限即只读文件,即500权限,但是write可写,如果没有这个参数,则不能创造新文件。如果文件已经存在,则第三个参数无效),O_EXCL(与O_CREAT一起用,那么如果之前文件已经存在,则返回失败)

creat相当于没有第二个参数的open,自带第二个参数(O_CREAT,OWRONLY,O_TRUNC)只有写权限,从头开始写。

未必能按照mode参数来创造文件,因为用户掩码(umask)会改变这个结果。
如果要创造需要的权限,可以在文件创造后,使用chmod来改变权限。
输入umask可以查看系统设置的值。一般是0022,即限制用户组和其他用户的写权限。

lseek设置文件指针位置,3个参数SEEK_SET(从文件头偏移),SEEK_CUR(从当前位置偏移),SEEK_END(从文件尾偏移)

stat,fstat,lstat以及一系列用于判断的宏定义,见P88页,也可以man stat
如果打开一个符号连接,stat返回指向的文件,lstat指向打开的这个链接。

标准IO库和windows里的基本相同,都是ANSI C的一部分。

r+ w+ 都是拥有读写权限,同样都是从文件头开始写入。

chmod,fchmod改变文件权限。

unlink,link 都和命令行里的命令一致,建立新的硬链接。
symlink相当于命令行里的ln -s 一样,建立符号链接,相当于windows里的快捷方式。

mkdir,rmdir 创建、删除目录
chdir,getcwd 改变、获得当前的工作目录

扫描目录系列函数看一下P103的例子就行了。

错误处理在errno.h文件里,出现错误后使用errno,这是个整型,显示错误号。
strerror将这个错误号变成具体的描述。
或者用perror直接把最近的错误内容打印出来。
在目前的版本里这个不需要自己定义全局变量,只要包括errno.h文件就行,和windows的一样,获得最后一次错误,拥有线程保护的,放心用。

fcntl可以做很多底层的事情,记住这个函数,以后在具体例子中慢慢研究。

mmap,msync,munmap允许程序共享内存,通过带特殊权限的虚拟内存段的话还可以用在文件的处理上。
感觉用它来读取结构化的文件挺方便的,可以看看P111的例子,以后应该的可以用到的。

另外无论使用open还是fopen后,手动删除掉该文件,那么后面的write和fwrite都会返回成功,但实际都是失败的。

四、linux环境

程序传递的参数,前面提到过:
如果执行应用程序给于参数是&,那么在main函数里获得的参数里是没有&这个参数的,如果&在中间,那么后面的参数全部无效,argc的参数数量也只记录&前面的参数。
linux里获得的第一个参数和windows一样,都是应用程序的执行路径。区别是windows是绝对路径,linux只是启动命令,如"./test.exe"

getopt和getopt_long可以用来解析输入参数。

getenv,outenv用来获得和新增环境变量,注意这个新增只影响自己,不会返回到父进程,即shell里面去。

extern char **environ (以NULL为结尾的字符串数组)可以获得所有的环境变量。

时间和日期和windows上的基本一致。
strftime使用的格式化转换控制符看P126页。

临时文件用tmpnam(是nam不是name)返回一个唯一标识符,但是如果是多个进程可能是一样的,所以最好用tmpfile直接打开一个文件。注意当这个文件流指针本关闭后,该文件会自动删除。
注意tmpnam的输入参数也是返回值,所以输入参数需要是一个足够长的字符串变量。

用户信息和日志等需要的时候再细看吧,现在也不是很了解linux的系统。

五 终端

六 curses