Linux 基本命令
Linux 文件类型:普通文件、目录文件、符号链接文件、设备文件、管道文件
删除非空目录:rm -r 目录名
Shell 编程
bash 脚本编辑后需给该文件设置可执行权限
shell 的所有变量都被看成字符串并以字符串格式存储
$$ 表示当前脚本的进程号
变量的声明
变量的赋值时 ”=“ 前后没有空格
字符串比较
算术比较
文件有关的条件测试
let 命令,shell 扩展$((表达式)),expr 命令这三种算术运算不支持浮点运算
数组的删除
删除某个下标
unset array[key],访问不了该下标,但不会报错,后面的下标也不会前移
删除整个数组
unset array
对数组的初始化多个 value 之间要用空格隔开
使用 “*” 进行乘法运算
使用 [ ] 命令测试表达式时,在操作数和操作符需要至少留一个空格
C语言开放工具
gcc *.c 生成的文件名为 a.out,其为可执行文件,但可以 gcc *.c -o 可执行文件 进行重命名
gcc 编译过程
- 编辑源代码 *.c
- 预编译:gcc *.c -o *.i -E
- 编译:gcc *.i -o *.s -S
- 汇编:gcc *.s -o *.o -c
- 链接:gcc *.o -o 可执行文件
gcc 编译器主要参数
-I(大写的i) dir 在头文件的搜索路径中添加dir目录
-L dir 在库文件的搜索路径中添加dir
-llibrary 连接名为library的库文件
-static 链接静态库
-c 生成目标文件(.o)
-S 生成汇编文件(.s)
-E 预编译,生成.i文件
-g 在执行代码中包含调试信息
-o file 把文件输出到file中
-v 显示gcc版本信息
函数库
- 静态库(a 库):对应 win 的 lib文件
- 共享库(默认,so 库):对应 win 的 dll 文件
makefile 中的变量名都大写
makefile 中常见自动变量
makefile 中的 5 部分内容:显示规则(创作者)、隐式规则(make 自动推导)、变量定义、文件指示、注释
gdb 调试的是可执行文件而不是 *.c 文件
系统函数的使用
生成 [0,1) 之间的值:rand()/(RAND_MAX+1.0)
rand() 和 srand() 函数在 头文件 stdlib.h 中
字符测试函数注意添加头文件 ctype.h
系统时间与日期函数
函数名
功能
asctime
将时间和日期以字符串格式表示
ctime
将时间和日期以字符串格式表示
gettimeofday
取得当前的时间
gmtime
把日期和时间转换为格林尼治时间的函
数
localtime
取得目前当地的时间和日期
mktime
将时间数据结构转换成经过的秒数
settimeofday
设置当前时间
time
取得系统当前的时间
\begin{array}{ll} \text { 函数名 } & \text { 功能 } \\ \text { asctime } & \text { 将时间和日期以字符串格式表示 } \\ \text { ctime } & \text { 将时间和日期以字符串格式表示 } \\ \text { gettimeofday } & \text { 取得当前的时间 } \\ \text { gmtime } & \text { 把日期和时间转换为格林尼治时间的函 } \\ & \text { 数 } \\ \text { localtime } & \text { 取得目前当地的时间和日期 } \\ \text { mktime } & \text { 将时间数据结构转换成经过的秒数 } \\ \text { settimeofday } & \text { 设置当前时间 } \\ \text { time } & \text { 取得系统当前的时间 } \end{array}
函数名 asctime ctime gettimeofday gmtime localtime mktime settimeofday time 功能 将时间和日期以字符串格式表示 将时间和日期以字符串格式表示 取得当前的时间 把日期和时间转换为格林尼治时间的函 数 取得目前当地的时间和日期 将时间数据结构转换成经过的秒数 设置当前时间 取得系统当前的时间
环境控制函数
getenv 函数
setenv 函数
lfind() 和 lsearch() 的不同:lsearch 找不到会放到数组中
文件 I/O 操作
文件类型分为普通文件(-),目录文件(d)、符号链接文件(l)、字符设备文件(c)、块设备文件(b)、管道文件(p)、socket文件(s)等,
system函数里面可以编写 shell 命令
chmod函数(修改文件权限):
chmod(文件名,权限参数)
权限参数:
S_IRUSR 所有者具有读权限
S_IWUSR 所有者具有写权限
S_IXUSR 所有者具有执行权限
S_IRGRP 组具有读权限
S_IWGRP 组具有写权限
S_IXGRP 组具有执行权限
S_IROTH 其他用户具有读权限
S_IWOTH 其他用户具有写权限
S_IXOTH 其他用户具有执行权限
不带缓存的 I/O 操作的主要函数:creat、open、close、read、write、lseek、flock、fcntl,都与文件描述符(STDIN_FILENO,STDOUT_FILENO,STDERR_FILENO)有关
非阻塞操作:flag |= O_NONBLOCK
阻塞操作:flag &= ~O_NOBLOCK
fcntl 函数
- 获得文件的 flags:flags=fcntl(fd,F_GETFL,0)
- 设置文件的 flags:fcntl(fd,F_SETFL,flags)
带缓存的流文件的 I/O 操作都是等缓冲区满了后再进行 I/O 操作,其主要函数如下:
函 数 | 作 用 |
---|---|
fopen | 打开或创建文件 |
fclose | 关闭文件 |
fgetc | 由文件中读取一个字符 |
fputc | 将一指定字符写入文件流中 |
fgets | 由文件中读取一字符串 |
fputs | 将一指定的字符中写入艾件内 |
fread | 从文件流成块读取数据 |
fwrite | 将数据成块写入文件流 |
fseek | 移动文件流的读写位置 |
rewind | 重设文件流的读写位置为文件开头 |
ftell | 取得文件流的读取位置 |
软链接文件和硬链接文件的区别:
- 软链接 Inode index 不一样,不同文件
- 硬链接 Inode index 一样,同一个文件多个名字
进程控制
进程操作包括对进程的中断操作、改变优先级、查看进程状态等
fork() 函数创建子进程,对应的 PID 返回两次:子进程为 0,父进程非零,父进程先运行,但两者是同步运行的,其中子进程复制父进程的数据段和对战,共享代码段
用 fork() 函数创建一个子进程后可使用 exec 函数族装入和运行其他程序,但调用该函数后不再与父进程共享代码段
终止进程的 5 种方式:
- 正常终止
- return
- exit
- _exit
- 异常终止
- abort
- 由一个信号终止
exit 和 _exit 的区别:exit 会清理 I/O 缓冲,即 _exit 前一行语句(包括回车符等)不会显示
僵尸进程:已终止运行但父进程未对其进行善后处理(仍占用资源)
孤儿进程:父进程创建了子进程而父进程又退出了,此时自动由 1 号进程(init 进程)收养它
避免僵尸进程:父进程中调用 waitpid 或 wait(waitpid 的一种特例),作用是使父进程阻塞
判断子进程的结束情况:
WIFEXITED(status): 如果子进程正常结束则返回非零值
WEXITSTATUS(status):取得子进程exit()返回的结束代码
WIFSIGNALED(status)如果子进程是因为信号而结束,则此宏值为真
WTERMSIG(status)取得子进程因信号而中止的信号代码,一般会先用WIFSIGNALED 来判断后才使用此宏。
WIFSTOPPED(status)如果子进程处于暂停执行情况则此宏值为真。一般只有使用WUNTRACED 时才会有此情况。
WSTOPSIG(status)取得引发子进程暂停的信号代码,一般会先用WIFSTOPPED 来判断后才使用此宏。
守护进程最重要的特性:后台运行,守护进程必须与其运行前的环境隔离开来
编写守护进程:
- 创建子进程,终止父进程
- 在子进程中创建新会话
- 改变工作目录
- 重设文件创建掩码
- 关闭文件描述符
代码
pid_t pid;
pid=fork();
if(pid<0)
{
printf"fork error\n");
exit(1);
}
else if(pid>0)
{
exit(0);
}
setsid();
chdir("/");
umask(0);
for(int i=0;i<NOFILE;i++)
{
close(i);
}
由于守护进程完全脱离控制终端,无法像普通程序一样用 gdb 正常调试。而是利用系统的日志服务(syslogd)
调用 openlog、syslog 函数,操作的系统日志文件 “var/log/syslog”,必须具有 root 权限
进程间的通信
常见的通信方式:
- 信号
- 管道 pipe
- 命名管道 FIFO
- 套接字 Socket
- 消息队列 MessageQueue
- 共享存储 SharedMemory
- 信号量 Semaphore
常见信号的含义及其默认操作:
信号操作的相关函数:
信号是软件层次上对中断机制的一种模拟,是一种异步通信方式
kill 函数用于给特定的进程或进程组发送信号,raise 函数用于向一个进程自身发送信号
信号阻塞:延迟一段时间再去调用信号处理函数
SIGINT(CTRL C)和 SIGTSTP(CTRL Z)可阻塞,SIGQUIT(CTRL \)不可阻塞
管道通信采用的是半双工方式,即同一时间只允许单方向传输数据
- 无名管道(pipe)
只能用于父子进程或兄弟进程之间(具有亲缘关系),只存在内存中,不与磁盘打交道
命名管道(mkfifo或mknod)
存在一个路径名与之关联,以 FIFO 文件的形式存储于文件系统中,能够实现任何两个进程之间的通信。在磁盘上有对应的节点,但没有数据块,不局限于父子进程之间的通信
消息队列常用函数:
共享内存是最快的一种进程间通信机制
共享内存有内存映射机制和 UNIX System V 共享内存机制两种实现方式,常用函数如下:
匿名内存映射适用于具有亲属关系的进程之间
线程
线程为进程内一个执行单元或一个可调度实体,进程是一个拥有资源的独立单位
线程的退出方式:
- 执行完后隐式退出
- pthread_exit,本身线程结束,对其他线程没有影响
- exit,会导致进程结束,从而导致所有线程结束
pthread_join 函数:挂起自身线程的运行,直到指定的线程结束
同步互斥机制
- 互斥锁
- 条件变量
- 信号量
应用互斥锁步骤:
- pthread_mutex_lock(&cat),加锁,锁定临界区
- 临界区的操作
- pthread_mutex_unlock(&cat),释放锁
条件变量允许线程阻塞和等待另一个线程发送信号的方法弥补了互斥锁的不足,常和互斥锁一起使用
常用的信号量函数: