文章目录
- 一、库
-
- (一)静态库
-
- [1. 概念](#1. 概念)
- [2. 制作](#2. 制作)
- [3. 使用(编译)](#3. 使用(编译))
- (二)动态库(共享库)
-
- [1. 概念](#1. 概念)
- [2. 制作](#2. 制作)
- [3. 生成可执行文件](#3. 生成可执行文件)
- [4. 基于动态库的可执行文件的执行过程](#4. 基于动态库的可执行文件的执行过程)
- 二、进程
一、库
库就是一个二进制文件,是将.c文件编译生成的二进制文件,
里面存放的就是函数实现的二进制的机器指令,库又分为静态库和动态库。
windows:
静态库: xxx.lib
动态库: xxx.dll
linux:
静态库: libxxx.a
动态库: libxxx.so
(一)静态库
1. 概念
静态库是以 libxxx.a
格式命名的 lib 是前缀 .a 是后缀 xxx 是库名
如果在编译时使用的是静态库,会将静态库中的机器指令编译到可执行文件中,
可执行文件的体积相对较大,执行效率相对较高。
静态库更新操作比较麻烦,需要重新编译生成可执行文件,否则拿不到新的库里的指令
2. 制作
bash
#首先,生成.o文件
gcc -c xxx1.c -o xxx1.o
gcc -c xxx2.c -o xxx2.o
....
#ar -cr 目标文件 依赖文件
ar -cr libxxx.a xxx1.o xxx2.o ....
3. 使用(编译)
(1)生成可执行文件
gcc 参数
bash
-I 指定头文件的路径
-L 指定库文件的路径
-l (小写的L)指定链接哪个库
(2)运行
无需指定库文件路径
(二)动态库(共享库)
1. 概念
动态库又叫共享库,是以 libxxx.so
命名的 lib 是前缀 .so 是后缀 xxx 是库名
如果在编译时使用的是动态库,只会将动态库中的函数符号表 编译到可执行文件中,
可执行文件的体积相对较小,执行时需要去动态库中找到对应的机器指令执行,效率相对较低。
动态库更新操作非常方便,只需要替换库即可,执行时自动就执行了新的库里的指令
2. 制作
bash
gcc -c -fPIC xxx1.c -o xxx1.o #-fPIC表示忽略相对位置
gcc -c -fPIC xxx2.c -o xxx2.o
...
gcc -shared xxx1.o xxx2.o ... -o libxxx.so #这种更常用
或者可以直接把.c编译成动态库
gcc -fPIC -shared xxx1.c xxx2.c -o libxxx.so
3. 生成可执行文件
与静态库类似
bash
-I 指定头文件的路径
-L 指定库文件的路径
-l (小写的L)指定链接哪个库
4. 基于动态库的可执行文件的执行过程
如果直接执行,会报错 找不到库文件。
运行前需要指定库的路径,指定库的路径可以用下面的方式:
方式1(相对更常用) :通过修改环境变量来实现----最常用的方式,必须会用
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:新的库的路径
//如果相对整个用户生效 可以把上面的指令放在 ~/.bashrc
中
方式2 :可以把自己的库放在系统默认的库的路径中----需要sudo权限
sudo cp libxxx.so /lib
或者
sudo cp libxxx.so /usr/lib
方式3 :可以通过修改系统的配置文件来实现----需要sudo权限
sudo vi /etc/ld.so.conf.d/libc.conf
在后面添加自己的库文件的路径即可
保存退出后 使用 sudo ldconfig
重新加载配置
将数据结构的相关函数封装为静态库
c
二、进程
(一)概念
1. 进程
程序的一次执行过程就会产生一个进程。
进程是分配资源的最小单位(0-3G)。
进程就是一个正在执行的任务。
进程是一个动态的过程,它有生命周期:随着程序的运行开始,随着程序结束而消亡。
每个进程都有自己的独立的运行的空间,比如
每个进程都有自己的文件描述符,每个进程都拥有自己的缓冲区。
只要用户执行了一个程序,在内核空间就会创建一个task_struct结构体,这个结构体就代表当前的进程。
进程运行产生的所有的信息都被放到这个结构体中保存着。
2. 进程和程序的区别
程序:程序是经过编译器编译生成的二进制文件,程序在硬盘上存储。
程序是静态的,没有生命周期的概念,程序本身不会分配内存。
进程:程序的一次执行过程就会创建一个进程,进程是动态的,有生命周期。
进程运行的时候会分配0-3G的内存空间。进程在内存上存储。
3. 进程的组成
进程是由三个部分组成的:进程的PCB(task_struct),(程序段)文本段,数据段。
4. 进程的种类
(1)交互进程
这种进程维护一个终端,通过这个终端用户可以和进程进程交互。例如:文本编辑器
(2)批处理进程
这种进程优先级比较低,运行的时候会被放到一个运行的队列中。
随着队列的执行,而逐渐执行。
例如gcc编译程序的时候这个进程就是批处理进程。
(3)守护进程
守护进程就是后台运行的服务,随着系统的启动而启动,随着系统的终止而终止。
例如:windows上的各种服务
PID就是操作系统给进程分配的编号,它是识别进程的唯一的标识。
在linux系统中PID是一个大于等于0的值。
在linux系统中创建的进程的个数是有限制的(通过如下命令查看)。
cat /proc/sys/kernel/pid_max
4194304
5. 特殊PID的进程
0:idle
:在linux系统启动的时候运行的第一个进程就是0号进程。
如果没有其他的进程执行就运行这个idle进程。
1:init
:1号进程是由0号进程调用内核kernel_thread函数产生的第一个进程,
它会初始化所有的系统的硬件。当初始化完之后会一直执行,比如会为孤儿进程回收资源。
2:kthreadd
:调度器进程,主要负责进程的调度工作。
(二)相关命令
1. ps 命令
c
linux@ubuntu:~$ ps -ef //用来查看进程的pid和ppid
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 5月29 ? 00:00:18 /sbin/init auto noprompt
root 2 0 0 5月29 ? 00:00:00 [kthreadd]
root 3 2 0 5月29 ? 00:00:00 [rcu_gp]
//UID 所属用的id
//PID 进程id
//PPID 父进程的PID
//C CPU占用率
//STIME 进程启动的时间
//TTY 是由否与之关联的终端 如果? 就表示没有
//TIME 进程占用CPU的时间
//CMD 运行进程的命令
linux@ubuntu:~$ ps -ajx //用来查看进程状态
PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
0 1 1 1 ? -1 Ss 0 0:18 /sbin/init auto nopr
0 2 0 0 ? -1 S 0 0:00 [kthreadd]
2 3 0 0 ? -1 I< 0 0:00 [rcu_gp]
//PGID 进程组id
//SID 会话id
//打开一个终端就会产生一个新的会话
//一个会话中可以有多个进程组 其中 前台进程组只有一个 后台进程组可以有多个
//每个进程组中又可以有多个进程
//TPGID 如果是-1 就表示是守护进程
//STAT 进程的状态
2. top和htop命令
- 注:htop命令需要自己安装
sudo apt-get install htop
c
top和htop命令
//动态的查看系统中进程的情况
进程号 USER PR NI VIRT RES SHR %CPU %MEM TIME+ COMMAND
91769 linux 20 0 2364 576 512 R 99.7 0.0 8:21.70 a.out
1704 linux 20 0 4894516 895980 59164 S 6.0 22.6 29:18.19 gnome-shell
1539 linux 20 0 319112 50656 18724 S 3.3 1.3 10:35.31 Xorg
3. pidof命令
pidof a.out //查看系统中所有名为a.out的进程PID
4.kill命令--给进程发信号的
kill -l //查看系统中的信号
bash
kill -2 pid //给进程发一个终止信号 (ctrl+c) 发出的信号
kill -9 pid //杀死一个进程
kill -19 pid //停止(暂停)一个进程
kill -18 pid //让停止的进程继续运行
killall a.out //杀死所有能操作的名为a.out的进程