栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

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

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

[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; 
	SElemType *top; 
	int stacksize; 
}SqStack; 

基本操作

void InitStack(SqStack *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)
{	
	free((*S).base);
	(*S).base=NULL;
	(*S).top=NULL;
	(*S).stacksize=0;
}

void ClearStack(SqStack *S)
{	
	(*S).top=(*S).base;
}

Status StackEmpty(SqStack S)
{	
	if(S.top==S.base)
		return TRUE;
	else
		return FALSE;
}

int StackLength(SqStack S)
{	
	return S.top-S.base;
}

Status GetTop(SqStack S,SElemType *e)
{ 
	if(S.top>S.base)
	{
		*e=*(S.top-1);
		return OK;
	}
	else
		return ERROR;
}

void Push(SqStack *S,SElemType 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)
{	
	if((*S).top==(*S).base)
		return ERROR;
	*e=*--(*S).top;
		return OK;
}

void StackTraverse(SqStack S,void(*visit)(SElemType))
{	
	while(S.top>S.base)
		visit(*S.base++);
	printf("n");
}

链表基本操作

#define DestroyList ClearList 
void InitList(LinkList *L)
{	
	*L=NULL; 
}

void ClearList(LinkList *L)
{	
	LinkList p;
	while(*L) 
	{
		p=*L; 
		*L=(*L)->next; 
		free(p); 
	}
}

Status ListEmpty(LinkList L)
{	
	if(L)
		return FALSE;
	else
		return TRUE;
}

int ListLength(LinkList L)
{	
	int i=0;
	LinkList p=L;
	while(p) 
	{
		p=p->next; 
		i++;
	}
	return i;
}

Status GetElem(LinkList L,int i,ElemType *e)
{	
	int j=1;
	LinkList p=L;
	if(i<1) 
		return ERROR;
	while(j
		j++;
		p=p->next;
	}
	if(j==i) 
	{
		*e=p->data;
		return OK;
	}
	else
		return ERROR;
}

int LocateElem(LinkList L,ElemType e,Status(*compare)(ElemType,ElemType))
{ 	
	
	
	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)
{	
	int j=1;
	LinkList p=*L,s;
	if(i<1) 
		return ERROR;
	s=(LinkList)malloc(sizeof(struct LNode)); 
	s->data=e; 
	if(i==1) 
	{
		s->next=*L;
		*L=s; 
	}
	else
	{	
		while(p&&j
			p=p->next;
			j++;
		}
		if(!p) 
			return ERROR;
		s->next=p->next;
		p->next=s;
	}
	return OK;
}

Status ListDelete(LinkList *L,int i,ElemType *e)
{	
	int j=1;
	LinkList p=*L,q;
	if(i==1) 
	{
		*L=p->next; 
		*e=p->data;
		free(p); 
	}
	else
	{
		while(p->next&&j
			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))
{	
	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有新的看法了吗,每个人心中都有自己的答案。

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

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/886488.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号