当前位置: 首页 > news >正文

复习总结最终版:Linux软件编程

一、Linux简介
(一)Linux内核是linux操作系统的核心
(二)内核主要功能
1.内存管理
2.多任务管理
3.文件系统管理
4.多任务间通信
5.网络管理
6.硬件设备管理
(三)Ubuntu是基于linux内核的操作系统之一,在内核基础扩展其他服务
1.桌面环境(如 GNOME)
2.办公 / 娱乐软件(浏览器、文档编辑器)
3.系统管理工具
(四)shell是内核的外壳
1.保护linux内核,防止用户直接操作内核导致异常
2.命令解释器作用,用户可以通过命令给到shell,shell转换为对应内核代码实现功能
二、shell命令
(一)常用命令
1.touch:创建文件
2.文件查看命令
①cat 文件名:查看文件中的内容
②head -n 行数 文件名:查看文件开头内容
③tail -n 行数 文件名
3.通配符:通常搭配shell常用命令,操作多个文件
①*(ls file*.txt):匹配任意长度,任意字符的文件名
②?(ls file_??.txt):匹配一位长度,任意字符的文件名
①[](ls file_[1-5].txt、ls file_[1,2,5].txt、ls file_[^3].txt):匹配一位长度,指定字符的文件名
4.管道(ls file* | grep ".sh"):前面命令的输出作为后续命令的输入
5.重定向:将原本要输出在终端的内容定向到指定文件中
①覆盖重定向:echo "hello world" > file.txt
②追加重定向:echo "hello world" >> file.txt
6.文件查找命令
①find . -name 文件名:查找文件
② find . -type f -print0 | xargs -0 grep -l "字符串":查找包含某个字符串的文件
③whereis valgrind:查找二进制可执行文件
7.常见命令
① echo "hello world":在终端显示内容
② grep "字符串" 文件名:查找包含字符串对应的行并显示
8.压缩和解压缩
①.tar.gz格式
解压:tar -zcvf 文件名.tar.gz 目录名/*
压缩:tar -zxvf 文件名.tar.gz
②.tar.bz2格式
解压:tar -jcvf 文件名.tar.bz2 目录名/*
压缩:tar -jxvf 文件名.tar.bz2
9.用户管理命令
①sudo useradd 用户名:新建用户
②sudo userdel 用户名:删除用户
③sudo passwd 用户名:修改密码
④ su 用户名:切换用户
exit 用户名:退出当前用户
⑤chmod 权限值(0777/0664) 文件名:修改文件权限,三组rwx
⑥chown 用户名 文件名:修改文件的所属用户
⑦chgrp 新组名 文件名:修改文件的所属组
(二)shell脚本
1.编程语言分类
①编译型语言:具有丰富的数据类型,擅长计算。需要先编译再运行,c、c++
②解释型语言:擅长对系统维护管理。边编译边执行,shell,python
2.shell脚本编程:本质是一系列shell命令的集合
3.编程步骤:
①编写脚本文件:vim filename.sh
②文件加权限:chomed +x filename.sh
③运行脚本:./filename.sh
4.指定脚本对应的运行shell:#!/bin/bash
5脚本的输入输出
①输入:从终端接收用户输入放入filename(read filename)
②输出:将filename值打印在终端(echo $filename)
6.shell脚本引用
①echo '$filename':原封不动打印引号中内容
②echo "$filename":将引号内容替换成对应值打印
③echo `seq 10`:将引号内容当作命令处理
7.shell中的变量
环境变量:shell自带,程序运行是就已经存在了
echo "$HOME"
echo "$PWD"
echo "$PATH"
...
位置变量
$0        :脚本的名称
$1      :执行脚本时传入的参数1
$2      :执行脚本时传入的参数2
..
$#      :传入参数的个数
$?      :上一条shell语句的执行结果
$$      :脚本运行的进程编号
自定义变量
value=0
$value
8.分支结构
①if分分支
if 表达式
then
语句块 
else
语句块
fi
②表达式可由test命令实现,test可用[]代替
-gt     #大于
-lt     #小于
-ge     #大于等于
-le     #小于等于
-eq     #等于
-ne     #不等于
-b      #检测文件是否存在,并判断是否为块设备
-c      #检测文件是否存在,并判断是否为字符设备
-d      #检测文件是否存在,并判断是否为目录文件
-e      #检测文件是否存在
-f      #检测文件是否存在,并判断是否为普通文件
-L      #检测文件是否存在,并判断是否为链接文件
-p      #检测文件是否存在,并判断是否为管道文件
-S        #检测文件是否存在,并判断是否为套接字文件
③cse分支
case 变量名 in
常量1)语句
;;
常量2)语句
;;
常量3)语句
;;
*)语句
;;
esac
9.循环结构
①while
while 表达式
do 
语句块
done
②until
until 表达式
do 
语句块
done
③for
for i in 数据集
do
语句块
done
10.数组
#!/bin/bash 
array=("hello" "world" "how" "are" "you")
i=0
echo ================================
for ((i = 0; i < 5; i++))                                           
do
echo ${array[$i]}
done

echo ================================
echo "${array[*]}"
11.函数
#!/bin/bash 
add()
{
sum=`expr $1 + $2`
echo "$sum"
return $sum
}
read num1
read num2
#获得函数内输出的字符串
ret=`add $num1 $num2`
#打印函数的运行的值
echo "$?"
#打印函数内输出的字符串
echo "ret = $ret"

三、IO
(一)文件分类
1.block(块设备):按块扫描信息的文件,称为块设备文件。通常存储类型的设备通常为块设备文件
2.character(字符设备文件):按字符扫描信息的文件,称为字符设备文件。一般设备通常为字符设备文件
3.directory(目录文件):目录文件,存放文件的文件夹
4.-(普通文件):存放信息的文件
5.link(链接文件):操作文件等价于操作文件指向的文件
6.socket(套接字文件):用来进程间通信
7.pipe(pipe):管道文件
(二)标准IO(通常用来操作普通文件)
1.文件类型
①ASCII码文件:文件中的所有内容均为能够在屏幕上显示的ASCII码字符
程序、文本文件均为ASCII码文件
②二进制文件:文件中的所有内容均为数据对应的二进制形式存放(包含一些不能在界面上显示的内容)
ASCII码文件也是二进制文件
图片、音视频、压缩包均为二进制文件
(三)标准IO函数接口(打开、操作、关闭)
1.fopen/fclose:打开(各种打开方式)pathname指向字符串对应的文件,并且和它建立一个流
2.fgetc/fputc:向流中写入/读取一个字符。ch = getchar()等价于 ch = fgetc(stdin)
3.fgets/fputs: 向流中写入str指向的字符串。fputs不会多打印\n字符,puts会多打印一个\n字符
从流中最多读size-1个字节数据放入s指向的空间中,遇到\n读取截止。gets会去掉从终端接收的\n字符,fgets不会去掉从终端接收的\n字符
4.fscanf/fprintf:
5.fread/fwrite:写和读
6.fseek/rewind/ftell
①fseek: 设置流的偏移量的标识
②ftell: 获得流的偏移量
③rewind:将流重新定位到开头
(四)标准IO是有缓存的IO:效率高,实时性差
1.全缓存(4k、与文件建立的缓存一般为全缓存):存满刷新、fflush函数强制刷新、fclose或者程序关闭刷新
2.行缓存(1k、与终端建立的缓存一般为行缓存(stdin、stdout均为行缓存)):存满刷新、\n刷新、fflush函数强制刷新、fclose或者程序关闭刷新
3.不缓存:出错处理或者人机交互一般使用不缓存(stderr不缓存)
(五)文件IO
1.文件IO没有缓存,适合于通信、硬件设备操作。
2.标准IO是库函数,文件IO是系统调用
3.库函数与系统调用
①系统调用:是Linux内核中的代码,只能在Linux系统中使用
②库函数:是对系统调用的封装,可以在不同的操作系统中安装并使用,库函数最终还是要调用系统调用完成对应功能
(六)文件IO函数接口(有三个特殊的文件描述符(非负整数、取未被占用最小非负整数、文件描述符是有上限的,到达上限后再打开会报错误):标准输入(0)、标准输出(1)、标准错误(2))
1.open        打开文件获得操作文件的文件描述符
close
2.read/write
3.lseek
4.文件IO与标准IO转换的函数
①. fileno:根据文件流指针获得文件描述符
②. fdopen:根据已经打开的文件描述符获得文件流指针
③. feof:判断文件流指针是否到达末尾
④. ferror:判断文件流指针是否出错
(七)目录IO
1.opendir: 打开目录流获得目录流指针
2.closedir
3.readdir:读取并返回下一个目录项的信息
4.getcwd: 获得当前工作目录的绝对路径
5.chdir: 切换当前的工作路径
6.mkdir
7.rmdir
8.  r:读权限,决定用户是否能够查看目录下所有文件名
w:写权限,决定用户是否能够在目录下新建文件
x:执行权限,决定用户是否能够进入目录
(八)时间相关函数(04-图)
1. time_t 类型时间(time、mktime):1970-1-1到现在的秒数、一般用于时间计算相关逻辑
2. struct tm 类型时间(localtime):包含年月日时分秒信息
3. char *字符串类型时间(ctime):由时间拼接的字符串
四、进程
(一)进程概念:是程序(存放在外存中的一段数据的集合)动态执行的过程,包括创建、调度、消亡
(二)进程创建
1.进程空间分布
①每个进程运行起来开辟0-4G虚拟内存空间
②进程空间:用户空间+内核空间(用户不能访问)
2.用户空间
①文本段(text):代码和指令,是只读的可被多个进程共享
②堆区(heap):程序员申请和释放。向高地址扩展、内存泄漏或堆碎片化
外部碎片化:空闲内存分散,无法合并成大块;
内部碎片化:分配的内存比实际请求的大(如对齐浪费)。
解决方法包括:
使用内存池减少小内存分配
选择高效分配器
避免频繁分配/释放
③栈区(stack):编译器自动分配和释放。存放局部变量,未经初始化值随机(执行到变量定义开辟空间,超过变量作用域回收空间)。向低地址扩展,递归过深、局部变量过大,会栈溢出
④数据段(全局变量、静态变量):编译时开辟,程序结束回收
.data(已初始化数据)
.bss(未初始化数据):写启动代码时,初始化未0
.rodata(只读数据):字符串常量、全局常量
3.虚拟地址和物理地址
①虚拟地址:c语言中*p操作的就是虚拟地址,操作此虚拟地址不会对硬件产生影响。32位操作系统2的32次方即最大开辟4G的空间(实际多个进程在一个不到4G的空间,宏观并行,微观串行)
②物理地址:ARM裸机操作的地址,内存存放数据对应的实际地址
③MMU(内存管理单元):将进程中的虚拟地址转换为随机物理地址(只有MMU知道)            
④写C语言时p存储的地址是虚拟地址(操作系统MMU开启),真实存储地址MMU有自己的映射,它自己知道。内核操作时(关闭MMU)我们直接操作的是物理地址
4.多进程存储(05-图)
5.进程相关命令
①top:根据CPU占用率和内存占用率查看当前所有进程的信息
②ps -ef:查看该时刻的所有进程信息
③ps -ef | grep 进程名:查找与进程名对应的进程信息
④ps -aux:查看该时刻的所有进程信息
⑤./a.out &:后台执行进程任务
⑥jobs:查看终端下所有的后台进程任务
⑦fg 编号(通过jobs查看):后台执行的任务放到前台执行
⑧nice -n 优先级编号 进程名、enice -n 优先级编号 进程PID:改变进程的优先级
⑨:kill -编号 进程PID、killall -编号 进程名:kill -9 PID
(三)进程相关函数接口
1.fok:创建新进程(06-图)
①子进程拷贝父进程文本段、数据段、系统数据段
②父子进程空间独立,两个进程代码一样,但是修改自己空间数据互不影响
③fok返回值不同:子进程返回0,父进程返回子进程PID
2.getpid和getppid
3.exit和_exit:结束进程任务并返回结束状态
4.wait:具有阻塞等待功能,等到有子进程结束然后回收子进程继续向下走。避免僵尸进程
5.waitpid:回收指定子进程
(四)进行消亡
1.孤儿进程:父进程先结束,子进程成为孤儿进程,被init进程收养
2.僵尸进程:是每个进程结束必然经历的阶段
产生原因:子进程结束后,父进程没有回收子进程空间,导致进程执行结束,空间依然被占用的状态,称为僵尸进程
解决办法:
①父进程先结束,子进程会成为孤儿进程,孤儿进程被init进程收养,子进程再结束,init进程回收进程空间
②父进程回收(wait、waitpid)
(五)exec函数族
1.exec函数族:利用进程空间执行另一份代码
2.exec常搭配fork使用,fork负责创建新的子进程,exec负责让子进程执行自己的代码
五、线程
(一)线程空间
1.线程必须位于进程空间内部,没有进程,线程无法独立存在
2.一个进程中的所有线程共享文本段+数据段+堆区,独享栈区(07-图)
3.线程独享的栈区默认为8M
4.区别
①进程:操作系统进行资源分配的基本单位(虚拟空间开辟)
②线程:CPU任务调度的最小单元。操作系统直接分配CPU时间片给线程,而不是进程
(二)多线程和多进程优缺点
1.效率(多线程 > 多进程):多线程在同一空间内部切换,多进程切换需要MMU重新映射物理地址
2.通信(多线程 > 多进程):多线程有共享空间,定义共享空间变量完成数据交换即可通信。
3.资源竞争(多线程 < 多进程):多线程需保证资源使用的互斥性,防止多线程对共享资源产生竞争。
4.安全(多线程 < 多进程):独立空间互相不会影响。进程内的一个线程奔溃,可能引发进程异常退出,导致其余线程也无法执行
(三)线程的函数接口
1.pthread_create
2.pthread_exit
3.pthread_join:tid对应的线程只要不退出,pthread_join阻塞等待结束回收线程空间
(四)线程传参:可以通过pthread_create第四个参数实现对线程内部的传参
(五)线程属性
1.加入属性:线程结束需要pthread_join手动回收,但可以回收到线程结束的状态
2.分离属性:线程结束后操作系统自动回收线程空间
六、线程间通信(全区变量)
(一)多线程同时操作共享空间会引发资源竞争,需要加上互斥锁解决资源竞争问题
(二)互斥锁
1.概念
①只能加锁一次,加锁期间不能再次加锁,也不能强制占有一个已经加锁的锁资源,必须等待锁资源释放,也就是解锁后才能继续操作该锁
②加锁和解锁中间的代码称为临界代码,也称为临界区    
③只能防止多个线程对资源的竞争,不能决定代码的先后执行顺序
④原子操作:CPU执行原子操作时无法切换调度任务
2.使用流程(解决资源竞争的一种方式,可以看成是一种资源。)
①定义互斥锁(全局变量)
②对锁初始化: pthread_mutex_init
③操作全局资源前先加锁:pthread_mutex_lock
④如果加锁成功则完成对全局资源操作
⑤如果加锁失败则表示有人占用资源,必须等待其余人释放锁资源才能加锁成功
⑥直到加锁成功使用该全局资源
⑤操作结束解锁: pthread_mutex_unlock
⑥销毁锁: pthread_mutex_destroy
3.死锁:多线程由于加锁解锁错误导致程序无法继续向下运行的状态称为死锁状态(08-图)
①产生条件
互斥条件
不可剥夺条件
请求保持条件
循环等待条件
②如何避免
加速顺序一致
使用pthread_mutex_trylock替换pthread_mutex_lock
(三)信号量(09-图)
1.概念
信号量是一种资源
如果信号量资源数为0,申请资源会阻塞等待,直到占用资源的任务释放资源,资源数不为0时才能申请到资源并继续向下执行
释放资源不会阻塞
2.操作
初始化:sem_init
销毁: sem_destroy
申请:sem_wait:    如果信号量资源数为0,则会阻塞等待,直到有任务释放资源,才能拿到资源并继续向下执行
释放:sem_post 
七、进程间通信(IPC)
(一)概念:因为0-4G虚拟空间内核是通用的,所以可以利用Linux内核实现多个进程间的通信
(二)管道
1.无名管道:只能用于具有亲缘关系的进程通信,通过在管道写和读实现通信
①简介:无名管道是一段内核缓存区,父进程通过pipe创建无名管道,只有父子进程才能获得文件描述符,实现通信
②函数:int pipe(int pipefd[2])
pipefd[0]:读管道文件描述符
pipefd[1]:写管道文件描述符
2.管道操作特性
①管道中至少有一个写端:有数据直接读出。无数据阻塞等待有数据才能读出
②无写端:有数据读出。无数据不阻塞等待
③有一个读端:管道没写满直接写入。管道存满先阻塞等待有数据读出才能继续写入
④无读端:写数据会管道破裂
2.有名管道:可以通过管道的名字找到该管道
①简介:可以用于任意进程间通信。进程通信最简单、最容易实现的方式。进程必须以读写的方式打开管道。
②函数:int mkfifo(const char *pathname, mode_t mode)
pathname:管道文件名
mode:权限            
(三)信号
1.概念:Linux系统中的信号主要实现应用层和内核层之间的信号通知
2.信号类型(kill -l查看)
SIGINT:中止信号(可以从键盘输入)        ctrl + c
SIGQUIT:退出信号(可以从键盘输入)       ctrl + \
SIGKILL:杀死进程信号
SIGSEGV:段错误信号
SIGPIPE:管道破裂信号
SIGALARM:定时时间到达信号
SIGCHLD:子进程结束时,父进程回收到该信号
SIGCONT:继续执行进程任务
SIGSTOP:停止进程任务
SIGTSTP:挂起信号(可以从键盘输入)       ctrl + z
SIGIO:异步IO信号
3.信号处理方式:9号信号(SIGKILL)和19号信号(SIGSTOP)不能被忽略和捕捉
①缺省:信号来了,按照默认方式处理
②忽略:信号来了,不处理信号
③捕捉:信号来了,按照用户自定义方式处理
4.函数
①signal(捕捉信号):使信号来了,按自定义方式执行
typedef void (*sighandler_t)(int);    //函数指针
sighandler_t signal(int signum, sighandler_t handler);     //设置signum对应信号的处理方式
ignum:信号的编号
handler:信号的处理方式
SIG_IGN:忽略信号
SIG_DFL:缺省处理信号
②alarm(定时时间到达信号):设置第一个定时,过seconds秒后,给进程发送SIGALRM信号
unsigned int alarm(unsigned int seconds)
③kill(给某进程发信号):给pid对应的进程发送sig信号
int kill(pid_t pid, int sig)
pid:进程的ID号
sig:信号的编号    
(四)IPC对象(消息队列、共享内存、信号灯创建的前提)
1.IPC对象简介
IPC对象可以看成在内核开辟了一个专门用于进程通信的空间(11-图)
每个IPC对象可以创建一个消息队列、一个共享内存、一个信号灯
IPC对象在操作系统关闭的情况下数据被回收掉
2.IPC对象操作命令
①查看IPC对象
ipcs -q/m/s:查看消息队列/共享内存/信号灯
②删除IPC对象
ipcrm -q/m/s:消息队列/共享内存/信号灯的ID
ipcrm -Q/M/S:IPC对象的Key值
3.函数:key_t ftok(const char *pathname, int proj_id)
pathname:路径
proj_id:项目ID(8位)
返回值:成功返回创建的IPC对象的名称
(五)消息队列
函数接口
①创建消息队列:int msgget(key_t key, int msgflg)
key:IPC对象的名称
msgflg:创建标志
IPC_CREAT   不存在创建
IPC_EXCL    存在报错
返回值:成功返回消息队列ID
②向消息队列中发送消息:int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg)
msqid:消息队列的ID号
msgp:发送消息内容空间的首地址
msgsz:发送消息内容的大小
msgflg:发送消息的标志
③从消息队列中接收消息:ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg)
msgqid:消息队列的ID号
msgp:存放消息空间的首地址
msgsz:最多接收消息的大小
msgtyp:接收消息的类型
④删除消息队列:int msgctl(int msqid, int cmd, struct msqid_ds *buf)
msqid:消息队列的ID号
cmd:IPC_RMID 删除类型
buf:默认为NULL
(六)共享内存
1.简介
进程间通信最高效形式
进程空间是独立的,共享内存是开辟一段内核空间,进程都映射到这一片空间上,实现空间的共享
2.函数接口
①创建共享内存:int shmget(key_t key, size_t size, int shmflg)
key:IPC对象的键值
size:共享内存空间大小
shmflg:IPC_CREAT    不存在创建
IPC_EXCL     存放报错
返回值:成功返回共享内存的ID号
②将进程空间中的地址映射到共享内存中:void *shmat(int shmid, const void *shmaddr, int shmflg)
shmid:共享内存的ID号
shmaddr:
NULL:系统选择一个合适的地址进行映射
shmflg:
标志默认为0
返回值:成功返回映射到共享内存空间中的地址
③解除映射:int shmdt(const void *shmaddr)
shmaddr:映射到共享内存空间中的地址
④向共享内存发送命令(发送删除命令):int shmctl(int shmid, int cmd, struct shmid_ds *buf)
shmid:共享内存ID号
cmd:命令
IPC_RMID    删除共享内存
buf:    
默认为NULL
(七)信号灯(搭配共享内存实现进程间通信)
1.简介
①信号灯是一组信号量,即信号量的数组
②用于线程间通信的信号量称为无名信号量,信号灯是有名信号量
2.函数
①创建信号量数组:int semget(key_t key, int nsems, int semflg)
key:IPC对象名称
nsems:信号量的个数
semflg:IPC_CREAT        不存在创建   
IPC_EXCL         存在报错
返回值:成功返回信号量数组的ID
②完成对一个信号量的操作:int semop(int semid, struct sembuf *sops, size_t nsops)
semid:信号量数组的ID号
sops:对信号量进行操作的空间的首地址
nsops:对信号量进行操作的个数
unsigned short sem_num:操作信号量的下标
short          sem_op:+1 释放1个资源  -1申请1个资源
short          sem_flg:对信号量的操作在进程结束后撤销
③利用cmd删除信号量数组的操作:int semctl(int semid, int semnum, int cmd, ...)
semid:信号量数组的ID号
semnum:操作的信号量的下标
cmd:IPC_RMID 删除信号量
SETVAL   设置信号量的值

http://www.dtcms.com/a/487190.html

相关文章:

  • 索泰显卡,索泰 firestorm 官方下载
  • 网站建设的主要内容包括网页框架结构有哪些
  • 公司做一个网站企业网站制作哪些公司制作
  • 青岛做外贸网站建设wordpress订阅关闭
  • 【个人成长笔记】在Ubuntu中的Linux系统安装实验室WIFI驱动安装(Driver for Linux RTL8188GU)
  • 腾讯音视频功能有哪些
  • 网站建设的流程与思路完美代码网站
  • 基于 GitLab CI/CD 与 Google Gemini 的 AI Code Review 自动化方案
  • 【Vue专题】前端JS基础Part1(含模版字符串、解构赋值、变量常量与对象)
  • 婚庆网站开发背景wordpress怎么改后台
  • 0.2、​​AI Agent 开发中 ReAct 和 MAS 的概念
  • 网站源码风险哈尔滨 门户网站
  • 那些企业网站做的漂亮怎么做免费公司网站
  • 【Go】--扩容机制
  • 网站上哪个做相片书好哈尔滨信息网租房信息
  • 电子商城官方网站做网站的需要什么资质证明
  • 外贸网站制作需求wordpress设置多语言
  • 怎么提Issue与PR
  • wordpress建站资源漂亮的网站设计
  • Flowise 任意文件读写漏洞 | CVE-2025-61913
  • 青岛网站建设平台纯静态网站
  • STM32基于can总线通信控制多个舵机/电机原理及代码
  • 图解AES密钥扩展与加密过程
  • ps如何做网站轮播图泰安企业建站公司哪里找
  • vue疑难解答
  • 【检索:Top K】12、非精准Top K检索权威指南:搜索引擎排序加速的核心技术与实战实现
  • 顺德品牌网站建设优惠做好公众号 网站建设
  • nullptr vs NULL:C/C++ 空指针的演变史
  • 深圳企业网站制作公司介绍网站防盗链设置
  • 搜索别人的网站是带logo的请问怎么做的精准广告投放