linux系统编程笔记
linux系统编程
https://www.bilibili.com/video/av29268873?from=search&seid=261713728998466977
linux系统编程简介
一、 linux基本命令
1.shell 查看当前shell类型
2. 目录结构
3.读写权限
修改权限 chmod 775 文件名
文字设定法
数字设定法
r:4 w:2 x:1
修改所有者和所属组(普通用户加sudo 使用超级用户权限)
注意:
mkdir 创建目录
rmdir 删除目录 智能删除空目录
rm -rf 递归删除 可以删除非空目录 (+f 强制删除)
4.符号链接( 软链接) 硬链接
符号链接(软链接) ln -s
硬链接 ln
硬链接计数变为0,才会被销毁; 而软链接只要指向的原.c文件被删除就失效
5. od 指定的显示格式
6. 查找与检索
find搜索文件
.表示当前目录 *通配符 表示任意文件 *表示任意
grep查找文件内容 -r表示递归查找
7.安装软件
8 .磁盘管理
mount 挂载
umount
fdisk -l 查看u盘是否接入系统 准备挂在
将/dev/sdb1 挂载到 新建的 /mnt/usb
且正常为了正常输出汉字 iocharset=utf8 或者 iocharset=gb2312 设置字符格式
最后umount取消挂载(类似于windows弹出u盘)
注意:当挂载在/mnt/usb 后 usb中原来存在的文件存在但不可见,直到卸载u盘才可以看到
9 .压缩包管理
tar cvf abc.tar abc tar xvf abc.tar abc
tar zcvf abc.tar.gz abc tar zxvf abc.tar.gz abc
tar jcvf abc.tar.bz2 abc tar jxvf abc.tar.bz2 abc -C ~/test(解压缩到指定目录)
三种压缩方式大小不一致
10 .进程管理
-
who 查看是谁登录终端
-
ps
ps aux
ps ajx
-
jobs 显示当前shell正在运行那些作业
fg+作业号 可以将作业唤醒切换到前台
bg+作业号 把停止的作业放到后台运行 -
kill 向指定的进程发送信号
.
kill -l 列出所有kill信号 可以向某个进程发送以下信号
将一个死循环.cpp文件编译生成的.out文件放图后台执行(./abc & ) 再用kill -9 6335杀死该进程
-
env 查看当前用户环境变量
11 .用户管理
useradd 创建新用户
userdel -r szr删除新用户 (-r的意思是把这个用户创建的文件都删掉)
su szr 切换用户
sudo su 变成超级用户
passwd 设置密码
12 网络管理
- ipconfig
- ping
桥接和nat nat与主机共用一个ip 桥接自己独立设置一个ip
13 其他命令
man 1 查看命令
man 2 查看函数
mode(最大权限) 0666 umask(掩码) 0022
touch创建文件时,文件默认权限为 mode&(~umask) 不能直接当做0666-0222 要看做 rw-rw-rw- 减掉 ----w–w- 变为rw-r–r-- 因为可能会出现mode权限值小于umask 当mode中没有的权限位 如 r-- 减掉 rw-时 变为— (用数字减会出问题)
关机命令
reboot 系统重启
14 ftp服务器 (跳过 设置不成功) nfs ssh
15 vi
16 共享库
gcc -c -fPIC *.c
-fPIC表示库之间为相对偏移 便于移植 生成.o文件
-c 表示只编译 不链接
静态库和共享库的区别
类似于 c++ 静态库动态库 共享库需要记录版本号
二、linux文件I/O
1.c标准函数与系统函数的区别
C语言中标准输入流、标准输出流、标准错误输出流 而且会有缓冲区,减少I/O操作 提高效率
在Linux中,所有对设备和文件的操作都使用文件描述符来进行。 Linux中一个进程启动时,都会打开3个文件:标准输入、标准输出和标准出错处理。这三个文件分别对应文件描述符0、1、2。
在C语言中,在程序开始运行时,系统自动打开3个标准文件:标准输入、 标准输出、标准出错输出。通常这3个文件都与终端相联系。因此,以前我们所用到的从终端输入或输出都不需要打开终端文件。系统自定义了3个文件指针stdin、stdout、stderr,分别指向终端输入、终端输出和标准出错输出(也从终端输出)。 标准输入流:stdin 标准输出流:stdout 标准错误输出流:stderr
2.PCB Process Control Block 进程控制块
概念:为了描述控制进程的运行,系统中存放进程的管理和控制信息的数据结构称为进程控制块(PCB Process Control Block),它是进程实体的一部分,是操作系统中最重要的记录性数据结构。它是进程管理和控制的最重要的数据结构,每一个进程均有一个PCB,在创建进程时,建立PCB,伴随进程运行的全过程,直到进程撤消而撤消。
file_struct结构体
内存空间:进程占用0-3G 内核占用3G-4G
当fopen(“abc”)时,返回一个FILE*指针,里面包括文件描述符句柄files_struct,通过查找内核里PCB里的files_struct(实际上files_struct是一个指针指向一个数组,存在各种编号对应文件描述符指向一个真正的文件)找到对应的设备文件即可调用打开成功。
open read write
int fd=open(“abc”,o_CREAT,0777);
返回的是未使用的最小的文件描述符
ulimit -a 查看各种限制个数 如 -n标识限制打开文件1024个
阻塞非阻塞
阻塞状态 等待键盘输入
1 #include<stdio.h>
2 #include <sys/types.h>
3 #include <sys/stat.h>
4 #include <fcntl.h>
5 #include<stdlib.h>
6 #include<unistd.h>
7 #include<string.h>
8
9 int main(void)
10 {
11
12 char buf[1024];
13 int len;
14
15 len=read(STDIN_FILENO,buf,sizeof(buf));
16 write(STDOUT_FILENO,buf,len);
17
18 return 0;
19 }
非阻塞读终端实验
errno 在头文件 #include<errno.h> 中 定义为一个全局变量 当函数调用失败会初始化
perror(“fail”) 会在屏幕中输出fail 并且将errno对应的具体错误类型输出在后面
lseek实验
(1)设置偏移量 拓展一个文件
(2)可以输出已有的文件大小
fcntl
open可以再打开时设置文件属性
fcntl 获取或者设置文件访问控制属性(对于已经打开的文件)
offset取值:F_GETFL S_SETFL
ioctl fcntl
ioctl用于设备特定的物理属性的访问和设置
三、linux文件系统
1.ext2文件系统
chown使用时必须是root权限
四、进程
PCB 一个task_struct结构体。
进程运行状态:
(1) fork
fork函数调用一次返回两次,在父进程返回子进程的pid,在子进程返回0,小于0表示fork失败。
getpid获取当前进程pid getppid获取当前父进程的pid
子进程和父进程取地址相同,都是同一个虚拟地址;但对应的物理地址不同,也就是说父进程栈上n=10,子进程复制过来n=10,父进程对n的操作对子进程无影响,子进程属于自己独立的内存空间。
读时共享,写时复制
节省物理内存开销:读的时候映射同一个物理内存;当出现写操作的时候,才会拷贝一份新的内容放在另一段物理内存中。
在用户user登录状态下sudo 有效用户root 实际用户为用户user
执行时设置用户ID chmod 04 777
从rwx变为rws, 在执行时有效用户变为文件的所有者root
vfork (渐渐淘汰掉了,因为fork的读时共享,写时复制已经取代它)
(2)exec
exec加载新的程序来替换当前进程代码段数据段等
execl第一个参数要给定完整路径;execlp给出文件名即可,会自动从PATH变量中寻找路径;execv第二个参数存放的是函数指针列表;execvp不需要完整路径,其余等同execv;execle通过最后一个参数替换命令行参数
事实上,只有execve才是真正的系统调用,其他5各函数都在execve,故execve在man手册第二节,其余函数在man手册第三节。 man(3)
(3)wait/waitpid
wait 是一个阻塞函数,等待回收子进程资源,返回子进程pid;如果没有子进程,wait返回-1(父进程wait的时候必须等待所有子进程结束才可以继续之后的操作,父进程效率很低)
waitpid 非阻塞 函数
(第一个参数四个状态 < -1 -1 0 >0)
第一个参数< -1: 回收指定进程组内的任意子进程
第一个参数-1:回收任意子进程
第一个参数0:回收和当前调用waitpid一个组的所有子进程
第一个参数>0:回收指定ID的子进程
第二个参数接收退出值
第三个参数 (可以设置WNOHANG 变为非阻塞函数)
僵尸进程(Zombie): 当子进程运行结束退出,而父进程还未结束,子进程进入僵尸进程状态,0-3G用户空间被回收,但内核空间pcb还存在等待父进程回收。 僵尸进程提供一种机制可以使父进程查看子进程到底如何结束,正常运行结束还是异常退出。
kill 666 杀死pid666的进程
kill -666 杀死属于666组的进程 (组ID就等于父进程的进程号)
孤儿进程: 父进程先于子进程结束,则子进程成为孤儿进程。 子进程的父进程称为1号进程init进程,称为init进程领养孤儿进程。
五、进程间的通信
1.pipe管道
管道一端读,一端写 (可以用队列实现)
int fd[2];
pipe(fd); //fd[0]管道读端(保存文件描述符3) fd[1]管道写端 (保存文件描述符4) 0 1 2 标准输入 标准输出 标准错误
确定通信方向(单工):(父子进程的文件描述符指向同一个结构体,如果父子可以同时通信同时对一个结构体写,会导致无法判断信息是哪个进程写的)
- 父写子读 关闭父读,关闭子写
- 子写父读 关闭子读,关闭父写
如果需要同时双向通信,需要建立两条管道
管道作用于有血缘关系的进程之间,通过fork来传递
使用管道考虑的四种情况:
fpathconf(int fd, int name)函数 返回管道缓冲区的大小:参数name为 _PC_PIPE_BUF
管道默认阻塞 ,若想设置为非阻塞管道,fcntl函数设置0_NONBLOCK标志
2.fifo有名管道
创建一个有名管道 ,解决无血缘关系 的进程通信
mkfifo myfifo //创建有名管道
- 两个无血缘关系的进程可以通过myfifo磁盘文件向pipe中分别读写数据,实现了二者之间的通信。(类似于一个中转站)
- 传递数据之后myfifo磁盘文件不会存储读写的内容,他只是提供一个索引指向pipe
3. 内存共享映射 mmap/munmap
共享映射 shared(内存文件更改,磁盘也发生变化) 似有映射 private(内存更改,磁盘不发生变化)
addr 内存中的映射地址,NULL表示随机系统分配
length 映射长度
prot 读 写 执行 禁止访问,申请内存的权限
flags MAP_SHRAED or MAP_PRIVATE 共享还是私有
fd 文件描述符,映射的文件
offset 4096整数倍的偏移量
返回值返回void* 指向内存空间的首地址
off必须是4096的整数倍 按页偏移
mmap实现进程间通信: