[IT鹅C/C++系列课程]靓仔我想学编程为什么给我讲操作系统?

Posted IT鹅

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[IT鹅C/C++系列课程]靓仔我想学编程为什么给我讲操作系统?相关的知识,希望对你有一定的参考价值。

Day01:
让我们重拾对梦中情人C和C++的热爱
[IT鹅C/C++系列课程]操作系统基础Operating System Fundamentals Course

一部“逆天”的“爽文”编程教程


BILIBILI IT鹅 BILIBILI@IT鹅

课程介绍:

[C/C++系列课程]操作系统基础Operating System Fundamentals Course
本课程使用了ICS与SP教学模式,用通俗易懂的语言讲解枯燥无味的C/C++,本课程将会从硬件、操作系统和编译系统对应用程序性能与正确性影响。SP是一门系统编程课程,当我们具备基本编码技能后,课程在后期从系统编程(Linux),进程、网络编程等方面做简易介绍。

前言:

文章多有不尽人意之处,希望学者朋友们能进行勘误建议,感激万分!

主流操作系统OS

主流操作系统包括Windows,MacOS,android,Linux等,严格来讲Android系统属于Linux系统的分支,Android系统基于Linux系统内核,主流的Ubunutu Debian发行版本也都是基于Linux Kernel,但是不同版本的Linux发行版本有不同的软件源,这也是为什么Linux发行版本良莠不一的原因之一。但是Linux系统拥有一个社区,全世界的开发者都可以向kernl.org提交自己对内核的贡献,报送Linux系统相关高位漏洞,Windows与MacOS是依据Unix设计的操作系统。

🤔️[疑问1]
Android系统与Linux系统关系?

Android是在Linux内核基础之上,Linux提供核心服务:安全、内存管理、进程管理、网络和驱动模型等。

有些老师可能会给你讲,Android系统属于外壳shell,而不是内核kernel
什么是shell?同学们也许会在某某逆天黑客小说里见过这个词语,黑客随手就是一个shell,中文译名壳,指的是人类于机器交互的命令解释程序,简单来讲,windows系统中,cmd属于shell,Linux上的bash属于shell,MacOS上的Terminal终端,bash又是什么(再简单来讲所谓黑客在电脑黑窗口里输入的装逼命令,下图是终端的截图
简单的装逼命令:

echo 靓仔专用shell
echo 靓仔你好

🤔 这也是编程??? 准确的来说,这就是shell能够理解的语言。

什么⬆️ 这就是shell?!

从曼切斯特机器时代到迷你计算机时代

大型机器时代

最早的计算机是没有任何形式的操作系统的大型机。1949年。最初的机器是曼切斯特1型商用计算机诞生,这是最早的存储程序计算机之一,每个用户在预定的时间段内单独使用机器,并带着程序和数据到达计算机,通常是打孔纸卡磁带纸带。该程序将被加载到机器中,并且机器将被设置为工作,直到程序完成或崩溃。程序通常可以通过控制面板使用转盘、拨动开关和面板灯进行调试。

后来,机器引入帮助程序输入输出工作的代码库,什么是代码库(codebase)
一般指的是人工编写的源代码文件,然而每次机器只能执行一次任务。

迷你电脑时代

UNIX操作系统是在 1960 年由AT&T公司的贝尔实验室开发出来的,这是一个由C语言编写的系统,那么UNIX是如何工作的,本文不细致介绍。但是你需要了解到,UNIX操作系统是一个划时代的产物,由于C语言具备可移植的特性,所以UNIX可以进行再不同硬件设备上进行移植。
(补充一下C语言的历史:从前文学习了C语言的基本概况让我们重拾对梦中情人C和C++的热爱
C语言于1969年至1973年间,为了移植与开发UNIX操作系统,由丹尼斯·里奇与肯·汤普逊,以B语言为基础,在贝尔实验室设计、开发出来。

Apple与DOS之后的时代

微型处理器的发展使计算机的应用普及至中小企业及个人爱好者。而计算机的普及又推动了硬件组件公共接口的发展。早期计算机中主要的操作系统是8080/8085/Z-80 CPU用的CP/M-80。这些计算机在ROM(只读存储器)都有一个小小的启动程序,可以把操作系统从磁盘装载到内存。IBM-PC系列的Bios是这一思想的延伸。自1981年第一台IBM-PC诞生以来,BIOS的功能得到不断地增强。

回到本文重心,此时我们又有**【疑问2】🤔️**
最初的操作系统如何移植到计算机上面的?

关于操作系统历史知识请参考:RedHat代码英雄 Linux中国

现代操作系统

操作系统精髓与设计原理

操作系统纲要:

内核:

内核系统架构:

Exokernel外核心 **Hybrid Kernel 混合核心(Monolithic kernel&Micro Kernel)微内核(Microkernel,μ-kernel)宏内核(Monolithic kernel)单一内核(Unikernel) **

内核组件

驱动程序(driver) 可加载核心模块LKM(Loadable kernel module)微内核(Micro Kernel)用户空间(User Space)

概念:
上下文切换(content Switch):多任务处理multitasking 中断处理 Interrupt tasking 用户态与内核台切换user mode switch to kernel mode
中断:interrupt,顾名思义,当我们的计算机硬件或者OS接收到某个特殊的信号的时候,计算机会立刻停手中的工作,去做另外一件事情,完成任务后,再继续做手上的任务。好比,当你在学习的时候,好兄弟叫你出去打羽毛球,打完羽毛球后,你又要开始学习之旅,这样的定义并不专业,但是我们可以这样简易理解中断。
专业一点(重点):
硬件中断(Hardware Interrupt)
软件中断(Software Interrupt)
由于软中断指令通常要运行一个切换CPU至内核态(Kernel Mode/Ring 0)的子例程,它常被用作实现系统调用(System call)

进程间通信

IPC,Inter-Process Communication),指至少两个进程或线程间传送数据或信号的一些技术或方法。进程是计算机系统分配资源的最小单位(严格说来是线程).每个进程都有自己的一部分独立的系统资源,彼此是隔离的。为了能使不同的进程互相访问资源并进行协调工作,才有了进程间通信。

IPC通信应用:Web服务器,我们在通过网页使用进程通信来共享web文件(html

进程(process)

我想命令计算机,这个时候操作系统就会产生进程,同一个程序可以产生多个进程(一对多的关系),进程运行效率取决于CPU运行效率。
划重点:进程与线程的区别:进程是计算机管理运进程序的一种方式,一个进程下可包含一个或者多个线程。线程可以理解为子进程。线程是进程的子集。

进程控制块(Process Control Block,PCB)

操作系统核心的数据结构,主要是为了表示进程状态,it included process status,it can be new, ready, running, waiting and blocked and so on。
(不知道为什么这里就飙洋文了,同学们理解下,计算机用洋文讲的更明白)CPU寄存器(累加器accumulator)变址器,堆栈指针(stack pointer)

靓仔等等,什么是Stack Pointer,这是一个似曾相识的名字,没错堆栈指针很重要!那么下面就简单介绍下堆栈指针。(枯燥乏味的堆栈指针以后能经常用上)

计算机中重要的ADT:

ADT:Abstract Data Type抽象数据类型
本小节鹅带你简单了解堆栈

堆栈(Stack),俗称,拼音字母(zhan),客栈的“栈”。

堆栈两种基本操作:(压栈,push)与(出栈,pop
特点: 先进后出,后进先出。
C语言中我们用一个叫做链表(linked list)的数据结构来描述,请观察下图并描述特点

堆栈可以用数组和链表两种方式实现。
下面这段程序来自高一凡《数据结构》算法实现及解析2004年10月第2版
存储结构:

#define STACK_INIT_SIZE 10 /* 存储空间初始分配量 */
#define STACK_INCREMENT 2 /* 存储空间分配增量 */
typedef struct SqStack

	SElemType *base; /* 在栈构造之前和销毁之后,base的值为NULL */
	SElemType *top; /* 栈顶指针 */
	int stacksize; /* 当前已分配的存储空间,以元素为单位 */
SqStack; /* 顺序栈 */

基本操作

/* bo3-1.c 顺序栈(存储结构由c3-1.h定义)的基本操作(9个) */
void InitStack(SqStack *S)
	/* 构造一个空栈S */
	(*S).base=(SElemType *)malloc(STACK_INIT_SIZE*sizeof(SElemType));
	if(!(*S).base)
		exit(OVERFLOW); /* 存储分配失败 */
	(*S).top=(*S).base;
	(*S).stacksize=STACK_INIT_SIZE;


void DestroyStack(SqStack *S)
	/* 销毁栈S,S不再存在 */
	free((*S).base);
	(*S).base=NULL;
	(*S).top=NULL;
	(*S).stacksize=0;


void ClearStack(SqStack *S)
	/* 把S置为空栈 */
	(*S).top=(*S).base;


Status StackEmpty(SqStack S)
	/* 若栈S为空栈,则返回TRUE,否则返回FALSE */
	if(S.top==S.base)
		return TRUE;
	else
		return FALSE;


int StackLength(SqStack S)
	/* 返回S的元素个数,即栈的长度 */
	return S.top-S.base;


Status GetTop(SqStack S,SElemType *e)
 /* 若栈不空,则用e返回S的栈顶元素,并返回OK;否则返回ERROR */
	if(S.top>S.base)
	
		*e=*(S.top-1);
		return OK;
	
	else
		return ERROR;


void Push(SqStack *S,SElemType e)
	/* 插入元素e为新的栈顶元素 */
	if((*S).top-(*S).base>=(*S).stacksize) /* 栈满,追加存储空间 */
	
		(*S).base=(SElemType *)realloc((*S).base,((*S).stacksize+STACK_INCREMENT)*sizeof(SElemType));
		if(!(*S).base)
			exit(OVERFLOW); /* 存储分配失败 */
		(*S).top=(*S).base+(*S).stacksize;
		(*S).stacksize+=STACK_INCREMENT;
	
	*((*S).top)++=e;


Status Pop(SqStack *S,SElemType *e)
	/* 若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERROR */
	if((*S).top==(*S).base)
		return ERROR;
	*e=*--(*S).top;
		return OK;


void StackTraverse(SqStack S,void(*visit)(SElemType))
	/* 从栈底到栈顶依次对栈中每个元素调用函数visit() */
	while(S.top>S.base)
		visit(*S.base++);
	printf("\\n");

链表基本操作

/* bo2-8.c 不带头结点的单链表(存储结构由c2-2.h定义)的部分基本操作(9个) */
#define DestroyList ClearList /* DestroyList()和ClearList()的操作是一样的 */
void InitList(LinkList *L)
	/* 操作结果:构造一个空的线性表L */
	*L=NULL; /* 指针为空 */


void ClearList(LinkList *L)
	/* 初始条件:线性表L已存在。操作结果:将L重置为空表 */
	LinkList p;
	while(*L) /* L不空 */
	
		p=*L; /* p指向首元结点 */
		*L=(*L)->next; /* L指向第2个结点(新首元结点) */
		free(p); /* 释放首元结点 */
	


Status ListEmpty(LinkList L)
	/* 初始条件:线性表L已存在。操作结果:若L为空表,则返回TRUE,否则返回FALSE */
	if(L)
		return FALSE;
	else
		return TRUE;


int ListLength(LinkList L)
	/* 初始条件:线性表L已存在。操作结果:返回L中数据元素个数 */
	int i=0;
	LinkList p=L;
	while(p) /* p指向结点(没到表尾) */
	
		p=p->next; /* p指向下一个结点 */
		i++;
	
	return i;


Status GetElem(LinkList L,int i,ElemType *e)
	/* L为不带头结点的单链表的头指针。当第i个元素存在时,其值赋给e并返回OK,否则返回ERROR */
	int j=1;
	LinkList p=L;
	if(i<1) /* i值不合法 */
		return ERROR;
	while(j<i&&p) /* 没到第i个元素,也没到表尾 */
	
		j++;
		p=p->next;
	
	if(j==i) /* 存在第i个元素 */
	
		*e=p->data;
		return OK;
	
	else
		return ERROR;


int LocateElem(LinkList L,ElemType e,Status(*compare)(ElemType,ElemType))
 	/* 初始条件:线性表L已存在,compare()是数据元素判定函数(满足为1,否则为0) */
	/* 操作结果:返回L中第1个与e满足关系compare()的数据元素的位序。 */
	/*           若这样的数据元素不存在,则返回值为0 */
	int i=0;
	LinkList p=L;
	while(p)
	
		i++;
		if(compare(p->data,e)) /* 找到这样的数据元素 */
		return i;
		p=p->next;
	
	return 0;


Status ListInsert(LinkList *L,int i,ElemType e)
	/* 在不带头结点的单链线性表L中第i个位置之前插入元素e */
	int j=1;
	LinkList p=*L,s;
	if(i<1) /* i值不合法 */
		return ERROR;
	s=(LinkList)malloc(sizeof(struct LNode)); /* 生成新结点 */
	s->data=e; /* 给s的data域赋值 */
	if(i==1) /* 插在表头 */
	
		s->next=*L;
		*L=s; /* 改变L */
	
	else
		/* 插在表的其余处 */
		while(p&&j<i-1) /* 寻找第i-1个结点 */
		
			p=p->next;
			j++;
		
		if(!p) /* i大于表长+1 */
			return ERROR;
		s->next=p->next;
		p->next=s;
	
	return OK;


Status ListDelete(LinkList *L,int i,ElemType *e)
	/* 在不带头结点的单链线性表L中,删除第i个元素,并由e返回其值 */
	int j=1;
	LinkList p=*L,q;
	if(i==1) /* 删除第1个结点 */
	
		*L=p->next; /* L由第2个结点开始 */
		*e=p->data;
		free(p); /* 删除并释放第1个结点 */
	
	else
	
		while(p->next&&j<i-1) /* 寻找第i个结点,并令p指向其前驱 */
		
			p=p->next;
			j++;
		
		if(!p->next||j>i-1) /* 删除位置不合理 */
			return ERROR;
		q=p->next; /* 删除并释放结点 */
		p->next=q->next;
		*e=q->data;
		free(q);
	
	return OK;


void ListTraverse(LinkList L,void(*vi)(ElemType))
	/* 初始条件:线性表L已存在。操作结果:依次对L的每个数据元素调用函数vi() */
	LinkList p=L;
	while(p)
	
		vi(p->data);
		p=p->next;
	
	printf("\\n");

回到进程管理的介绍。
实时操作系统(Real-time operating system, RTOS)

实时操作系统与一般的操作系统相比,最大的特色就是“实时性”.如果有一个任务需要执行,实时操作系统会马上(在较短时间内)执行该任务,不会有较长的延时。这种特性保证了各个任务的及时执行。

线程:

线程(thread)是操作系统能够进行运算调度的最小单位。大部分情况下,它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。在Unix System V及SunOS中也被称为轻量进程(lightweight processes),但轻量进程更多指内核线程(kernel thread),而把用户线程(user thread)称为线程。

C++11标准创建线程:
(这里同学们不太了解什么是C++11的,可以去看我的B站视频,或者前一篇文章)

C++11标准线程简介:

2011年8月12日,国际标准化组织(ISO)发布的ISO C++标准,C++11首次引入了C++标准线程,Windows平台运行的VS2012和Linux平台运行的g++4.7,都完美支持C++11线程。
头文件是thread
C++11创建线程实现原型

std::thread::thread(Function&& f, Args&&... args);

等待线程结束:

std::thread::join();

脱离线程控制:

std::thread::detach();

交换线程:

std::thread::swap(thread& other);

C++11相关函数:
创建线程:

int thrd_create(thrd_t *thr, thrd_start_t func, void *arg);

结束本线程:

_Noreturn void thrd_exit( int res );

等待线程运行完毕:

int thrd_join(thrd_t thr, int *res);

返回当前线程的线程标识符:

thrd_t thrd_current();

补(tu)充(cao):Java线程(Java就是名词多)
1.Thread/Runnable的run()方法运行完毕终止。
2.使用Future类的cancel()方法调用。
3.调用线程池的shutdown()和shutdownNow()的方法
4.守护线程会在非守护线程都结束时自动终止。
分时系统

分时系统(time-sharing)是计算机科学中对资源的一种共享方式,利用多道程序与多任务处理使多个用户可以同时使用一台计算机。

本系列课程遵循 署名-非商业性使用 3.0 中国大陆 (CC BY-NC 3.0 CN)
转载请标明 CSDN @IT鹅

写在最后的话:

相信同学们上完本次课后,相信你学习了许多奇奇怪怪的名词,也有更多的疑了,这是正常的,因为本节课将操作系统梳理了一遍。那么你的脑海里是否有对计算机学习的热情吗,那么你是否对OS有新的看法了吗,每个人心中都有自己的答案。

⛽️⛽️⛽️(被迫走上流量之路的企鹅~~~)靓仔点个关注➕再走⛽️⛽️⛽️

创作打卡挑战赛 赢取流量/现金/CSDN周边激励大奖

以上是关于[IT鹅C/C++系列课程]靓仔我想学编程为什么给我讲操作系统?的主要内容,如果未能解决你的问题,请参考以下文章

我想学编程,应该学哪一类,求助

我想学C++!!!

我想学编程,算是兴趣吧。先从C开始还是JAVA,需要用到啥软件,最好是能给网址、里面软件是现在还

LAZARUS是啥软件呀???哪位高手知道?我想学这个怎么样呢?

软件开发工程师需要掌握那些编程语言?

易道云C++零基础到大神全栈课程