Linux,是一种免费使用和自由传播的类UNIX操作系统,是一个基于POSIX的多用户、多任务、支持多线程和多CPU的操作系统。它能运行主要的Unix工具软件、应用程序和网络协议。Linux继承了Unix以网络为核心的设计思想,是一个性能稳定的多用户网络操作系统。博主将全程带领大家学习Linux的相关知识,本系列文章参考《鸟哥的Linux私房菜》推荐大家进行阅读学习。
计算机的硬件组件组成:
操作系统(OS):任何计算机系统都包含的一个基本的程序集合。
操作系统包括:
操作系统的设计目的:
计算机管理硬件(先组织再描述):
系统调用和库函数概念:
进程 = 内核数据结构 + 代码 + 数据
进程控制块 PCB(process control block):进程信息被放在一个叫做进程控制块的数据结构中,可以理解为进程属性的集合。
Linux - PCB:task_struct
typedef struct task_struct {//进程所有属性//进程代码地址
} PCD;
task_ struct内容分类
可以在内核源代码里找到它。所有运行在系统里的进程都以task_struct链表的形式存在内核里。
方法一
大多数进程信息可以使用top
和ps
这些用户级工具来获取
ps axj | head -1 && ps axj | grep "进程名"
方法二
进程的信息可以通过/proc
系统文件夹查看
ls /proc
方法三
通过系统调用获取进程标示符
#include
#include
#include using namespace std;int main() {printf("我的进程ID:%d\n", getpid());printf("我的父进程ID:%d\n", getppid());return 0;
}
fork函数基本功能
#include
#include
#include
using namespace std; int main() { pid_t ret = fork(); printf("进程ID - id: %5d, pid: %5d, ppid: %5d\n", ret, getpid(), getppid()); sleep(1); return 0;
}
此时会发现输出了两次不同的结果
通过fork()的返回值进行分流处理
#include
#include
#include using namespace std; int main() { int ret = fork(); if (ret > 0) { //father printf("父进程ID - id: %5d, pid: %5d, ppid: %5d\n", ret, getpid(), getppid()); } else if (ret == 0) { //child printf("子进程ID - id: %5d, pid: %5d, ppid: %5d\n", ret, getpid(), getppid()); } else { perror("fork"); return 1; } sleep(1); return 0;
}
进程队列数据结构
struct runqueue {PCD *head;//其他属性
};
操作系统控制图解
一个进程可以有几个状态(在 Linux内核里,进程有时候也叫做任务)
下面的状态在kernel源代码里定义:
/*
* The task state array is a strange "bitmap" of
* reasons to sleep. Thus "running" is zero, and
* you can test for combinations of others with
* simple bit tests.
*/
static const char* const task_state_array[] = {"R (running)", /* 0 */"S (sleeping)", /* 1 */"D (disk sleep)", /* 2 */"T (stopped)", /* 4 */"t (tracing stop)", /* 8 */"X (dead)", /* 16 */"Z (zombie)", /* 32 */
};
状态 | 意义 |
---|---|
R运行状态(running) | 运行 - 并不意味着进程一定在运行中,它表明进程要么是在运行中要么在运行队列里。 |
S睡眠状态(sleeping) | 浅度睡眠 - 意味着进程在等待事件完成(这里的睡眠有时候也叫做可中断睡眠 (interruptible sleep))。 |
D磁盘休眠状态(Disk sleep) | 深度睡眠 - 有时候也叫不可中断睡眠状态(uninterruptible sleep),在这个状态的进程通常会等待IO的结束。 |
T停止状态(stopped) | 暂停 - 可以通过发送 SIGSTOP 信号给进程来停止(T)进程。这个被暂停的进程可以通过发送 SIGCONT 信号让进程继续运行。 |
t追踪停止状态(tracing stop) | 表示程序正在被追踪(GDB调试时便是该状态) |
X死亡状态(dead) | 这个状态只是一个返回状态,你不会在任务列表里看到这个状态。 |
示例代码
#include using namespace std; int main() { while (true) { int a = 1; a += 1;} return 0;
}
在访问显示器时绝大多数情况都是在阻塞状态,只有极少情况下是在运行状态,我这里将两种情况都进行了截屏。
示例代码
#include using namespace std; int main() { while (true) { cout << "Runing~" << endl; } return 0;
}
暂停进程 -> 继续运行,可以看到R+变成了R,这是因为程序从前台运行变成了后台运行,并且^C无法终止调程序,需要使用kill命令的-9选项杀死进程。
kill -19 #暂停进程
kill -18 #继续运行
kill -9 #杀死进程
kill指令
僵尸进程概念
僵死状态(Zombies)是一个比较特殊的状态。当进程退出并且父进程(使用wait()系统调用,后面讲) 没有读取到子进程退出的返回代码时就会产生僵死(尸)进程。
僵死进程会以终止状态保持在进程表中,并且会一直在等待父进程读取退出状态代码。
只要子进程退出,父进程还在运行,但父进程没有读取子进程状态,子进程进入Z状态。
示例代码
#include
#include
#include using namespace std;int main() {pid_t id = fork();if (id < 0) {perror("fork");return 1;} else if (id > 0) {cout << "parent - pid : " << getpid() << endl;sleep(30);} else {cout << "child - pid : " << getpid() << endl;sleep(5);exit(EXIT_SUCCESS);}return 0;
}
运行脚本
while :; do ps axj | head -1 && ps axj | grep text | grep -v grep; sleep 1; done
< defunct >表示失效,此时进程已经死亡,但是没有被回收。将父子进程都终止的时候,操作系统自动回收工作。
僵尸进程的危害
孤儿进程概念
示例代码
#include
#include
#include using namespace std;int main() {pid_t id = fork();if (id < 0) {perror("fork");return 1;} else if (id == 0) { //childcout << "child - pid : " << getpid() << endl;sleep(10);} else { //parentcout << "parent - pid : " << getpid() << endl;sleep(3);exit(0);}return 0;
}
优先级的必要性:需求量大,资源太少,需要进行分配管理。
优先级的查看
ps -la
PRI 与 NI
优先级的修改
top命令更改已存在进程的nice: 输入top
-> 按r
-> 输入进程PID -> 输入nice值
top
r
30613 # PID的值
9 # nice的值
上一篇:JVM相关面试题
下一篇:第2章 信息系统项目管理基础