- 博客(44)
- 收藏
- 关注
原创 Linux多线程[二]
而且对于资源来说一个线程多次申请资源的时候,他一直申请到资源,别的线程申请不到资源,就造成了线程饥饿。所以就有了线程同步的概念。给线程角色化,承担不同的角色,而中间的超市本质上数据结构形成的缓冲区,商品是数据。生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生产完数据之后不用等待消费者处理, 直接扔给阻塞队列,消费者不找生产者要数据,而是直接从阻塞队列里取,检测的本质其实对临界资源的访问,那么对于临界资源的检测也是需要加锁和解锁的。按照一定的顺序,进行资源的访问,就叫做线程的同步。
2024-02-15 20:08:59 403
原创 Linux多线程[一]
库映射到内存中是线性的,为了更快的找到对应的线程资源,就使用起始地址来当线程id。大部分情况,线程使用的数据都是局部变量,变量的地址空间在线程栈空间内,这种情况,变量归属单个 线程,其他线程无法获得这种变量。cpu内部有寄存器,cpu内部寄存器本质上是当前执行流的山下文,寄存器的空间是共享的,但是寄存器的内容是私有的,逻辑如下。多线程函数调度的时候很容易多个线程都调度同一个函数,很容易造成一个线程执行到一半准备返回结果,但是另一个线程开始执行对结果进行了处理之后,之前的线程返回结果覆盖率最新的结果。
2024-02-15 13:12:54 975
原创 C++——基础
这个是为了防止不正常的参数传递,有正常参数的值时候a=0不起作用,当参数不正常的时候a=0起作用。传值返回的时候,其实是拷贝了一份函数返回值的拷贝,作为返回值。C调用C++ 的时候在C++的头文件上使用extern "c",表明该C++的代码使用C来编译。1. inline是一种以空间换时间的做法,如果编译器将函数当成内联函数处理,在编译阶段,会。输出型参数 例如函数的交换,就不用使用指针了,直接起别名就好了。inline函数几乎解决了宏的缺点,兼具了宏的优点。在C++中C的函数是可以用的。
2024-02-14 11:54:04 849
原创 linux信号机制[二]
如果oldset和set都是非空指针,则先将原来的信号 屏蔽字备份到oset里,然后 根据set和how参数更改信号屏蔽字。每个信号只有一个bit的未决标志,非0即1,不记录该信号产生了多少次,阻塞标志也是这样表示的。,在阻塞信号集中“有效”和“无效”的含义是该信号是否被阻塞,而在未决信号集中“有 效”和“无效”的含义是该信号是否处于未决状态。NO对于我们传入的参数,他会先进行强制类型转换,如果等于1,执行默认行为,等于2忽略,都不等于才会执行调用对应的方法。唯一的差别是位图中的内容代表信号是否被阻塞。
2024-02-14 11:06:22 1113
原创 linux信号机制[一]
由于临界区,和临界资源的存在,在进入临界区访问呢临界资源的时候,必须要先申请一个信号量。通知临界区,提前预定访问临界资源。对临界资源访问的预定。只有我这个进程访问完成之后其他的资源才可以访问呢。首先信号和信号量是2个东西。linux信号本质上是一中通知机制,用户或者操作系统通过发送一定的信号。通知进程,某些事件已经发生,你可以在进行后续处理。结合进程,我们可以得出以下结论:a.进程必须有识别进程的能力b.为什么能识别信号呢?通过程序员的逻辑处理。
2024-02-13 12:38:01 1129
原创 基础IO[一]
文件=文件内容+属性文件在硬盘上放着,我们的流程->写代码->编译->运行->访问文件。那么本质上是谁在访问?是进程在访问。进程访问文件是需要通过接口来访问。文件在磁盘上放着,要向硬件写入文件,谁有权限呢?必须让操作系统提供接口,用户和操作之间提供一个软件层,来帮助用户访问文件。操作系统提供文件类的系统调用接口,语言上,对接口进行了封装,让接口进行更好的使用。而且系统级别的封装不具有跨平台的条件。
2024-02-12 20:39:48 954
原创 进程间通信[二]
3.为了更好的进行进阶区的访问,可以让多执行流,在访问时候的时候,任何适合,都只能有一个进程进入临界区——互斥。每一个进程进入临界资源的时候,都需要先申请信号量。就是一段内存映射到两个进程之中,这段内存就是双方都可以看到同一块公共空间,变具备了进程间通信的前提条件。把映射去掉,然后释放空间,这就是释放共享内存。当进程结束进程还存在 ipcs -m查看共享内存资源,因为他的生命周期随内核。进程通信的本质不同的进程是看到同一份资源,比如管道,共享内存,但是这也带来了一个时序问题,造成数据不一致。
2024-02-12 19:51:15 422
原创 进程间通信
前言进程具有独立性,进程想要通信其实是有难度的,与独立性相违背。进程通信的本质是让不同的进程看到同一份资源。为什么要进程之间互相通信:数据交互,控制,通知等目标。
2024-02-11 23:27:54 347
原创 动静态库原理
静态库.alib文件夹,存放着所有的库。我们想写了自己的部分功能实现和代码,很多个.0和.h 但是实现文件太多了,我们把它打包在一起就是静态库。那么如何打包呢?ar命令这样就会形成libhello.a的静态库打包我们可以在makefile里面来写那么做好只会该怎么发布呢?一般会有一个include文件夹,这个文件夹里面放着所有的头文件,还有lib文件夹,这个文件夹里面放着所有的库文件。然后把这个文件夹给对方。那么对方怎么用呢?gcc 头文件的默认搜素目录是/usr/include。
2024-02-11 17:53:36 365
原创 基础IO[三]
close关闭之后文件内部没有数据,stdout和stderr 他们一起重定向,只会重定向号文件描述符,因为一号和二号描述符虽然都是sydout,但是并不一样,而是相当于一个显示器被打开了2次。分别重定向到2个文件的写法和直接写道一个文件的写法。文件是在磁盘中的,磁盘里面有一个个扇区,文件存储在其中,需要对每一个分区进行管理【机械硬盘知识】分区是由一个个标准块组成的super block文件属性信息,块使用了多少,还有多少没用,剩下多大等。
2024-02-11 15:39:10 442
原创 基础IO[二]
文件磁盘文件——没有被打开内存文件——被进程中在内存中打开,文件只有被加载到内存中才可以被访问。进程控制模块PCB内部有一个指针:styruct files_struct* files。这个指针指向一张表,file_struct他是一个结构体,这个指针指向这个结构体变量。重点需要关注的是fd_array。里面的那个变量是一个宏定义,根据系统地差别,大小也有差别,是一个指针数组,代表可以打开文件数目地多少。结构体最后一个变量file也是一个结构体,包含了文件地全部信息,大小路径,版本号等。
2024-02-10 14:53:39 817
原创 进程控制[三]
这里我们可以发现代码里写着进程的开头和结尾,但是只有进程的开头没有结尾,这是因为进程替换会将当前数据所有的代码和数据进行替换包括已经执行的和没有执行的。子进程在加载新程序的时候父子进程代码必须分离,如果不替换的话子进程会影响父进程的代码。fork之后父子执行不同的代码,如果子进程想执行全新的代码呢?,进行程序的替换达到加载其他程序的功能,将新的程序和代码加载到磁盘重新建立映射关系。进程替换没有创建新的子进程,进程本身就存在子程序,只不过重新加载。不光c/c++写的,别的语言写的程序,如何调用呢?
2024-02-08 18:48:53 362
原创 进程控制[二]
我们可以使用系统给我们的退出码,但是我们也可以自定义。一定不在操作系统内部,如果在内部的话可以直接通过系统调用完成_exit直接能刷新出来。父进程创建子进程,要关心子进程的状态,因为是让子进程办事的。exit在代码的任何地方调用都直接表示进程的终止。status次低八位表示的是退出码:status>>8&0xff得到子进程退出码。获取子进程status:输出型参数,可以将子进程的退出码填充到这个变量里面。在这里有个疑问\n数据是保存在缓冲区的,这个缓冲区在哪里,是由谁维护的?可以获取最后一次退出的退出码。
2024-02-08 12:43:01 334
原创 进程控制[一]
数据:可能被修改,必须分开,在创建子进程的时候就直接拷贝。但是全部拷贝,可能会拷贝大量用不到的数据,所以在创建的时候读取的数据拷贝不需要读取的数据不拷贝,只有一份。因为不知道那些数据会被拷贝所以选择了写时拷贝将父子进程分离,需要的时候再拷贝。fork之后代码是父子之间全部代码共享。但是因为只有再fork的时候在会有不用的分支所以显得前面的没有变化。一般而言我们没有加载的过程。也就是说子进程要用父进程的代码和数据!所以子进程只能“使用”父进程的代码和数据。代码:都是不可写的,只能读取,可以保证数据的独立性。
2024-02-07 22:52:54 345
原创 进程地址空间
上面的运行结果我们产生了一下的问题和结论:同一个地址同时读取的时候读出来不同的值——这里的地址一定不是物理地址。而是线性虚拟地址。所有的语言地址都不是真实物理地址,而是虚拟地址。例如显卡等有多个寄存器都有独立的物理地址模块。有物理隔断,通过虚拟地址来帮他们串联在一起,这样子用户在看的时候会看到他们是一个整体。对于进程本身来说,进程只能看到操作系统想让他看到的,进程之间彼此独立,每个进程都认为他能访问全部的地址空间。内存本身是可以随时被读写的,很不安全,万一被恶意读写非常不安全。
2024-02-07 22:34:05 866
原创 运算符优先级小示例
等号的结合性是从右向左,即先算nums[sest++]部分即将num[sest]赋值给左边。左侧nums[src]的值被修改成nums[sest],此刻sest++.这条语句结束后src++;这个该先算哪一个呢?
2023-08-08 12:55:18 33
原创 文件操作以及缓冲区
在编写程序的时候,在打开文件的同时,都会返回一个FILE*的指针变量指向该文件,也相当于建立了指。每当打开一个文件的时候,系统会根据文件的情况自动创建一个FILE结构的变量,并填充其中的信息,字,文件状态及文件当前的位置等)。因为有缓冲区的存在,C语言在操作文件的时候,需要做刷新缓冲区或者在文件操作结束的时候关闭文。每个被使用的文件都在内存中开辟了一个相应的文件信息区,用来存放文件的相关信息(如文件的名。feof 的作用是:当文件读取结束的时候,判断是读取结束的原因是否是:遇到文件尾结束。
2023-07-27 16:31:11 208
原创 动态内存(二)
包含柔性数组成员的结构用malloc ()函数进行内存的动态分配,并且分配的内存应该大于结构的大。用户调用free可以释放结构体,但是用户并不知道这个结构体内的成员也需要free,所以你。1. 栈区(stack):在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结。如果我们的代码是在一个给别人用的函数中,你在里面做了二次内存分配,并把整个结构体返回给。所以,如果我们把结构体的内存以及其成员要的内存一次性分配好。了,并返回给用户一个结构体指针,用户做一次free就可以把所有的内存也给释放掉。
2023-07-27 02:26:59 74
原创 动态内存陷阱
这一点很重要,传值调用,是将变量的值传递,传址调用是将将变量的地址传递。并不是址传递而GetMemory函数,形参接收变量会开辟新的空间并将开辟的空间放到p中。在GetMemory函数返回p的地址的时候函数结束,p的地址被释放,str接收了p释放地址的空间,再访问的时候就非法访问,属于野指针。这里面还有一个问题GetMemory开辟的空间无法回收,malloc开辟之后函数销毁,也没有变量记录空间首地址,会导致内存无法释放。在函数GetMemory函数使用的时候传递str指针的时候传递的究竟是什么!
2023-07-27 01:05:33 71
原创 动态内存管理
对于上面的代码1. 空间开辟大小是固定的。2. 数组在申明的时候,必须指定数组的长度,它所需要的内存在编译时分配。我们在创建变量开辟空间的时候很多时候,开辟的空间是固定的,不够灵活,多了又浪费少了又不够,那么有没有什么办法能够灵活的开辟空间,避免这个情况呢?动态内存管理。
2023-07-26 01:09:10 60
原创 自定义类型——结构体、枚举、联合
结构体变量的定义int main()int x;int y;}p1;//声明类型的同时定义变量p1//定义结构体变量p2//初始化:定义变量的同时赋初值。struct Stu //类型声明//名字int age;//年龄//初始化int data;//结构体嵌套初始化//结构体嵌套初始化return 0;
2023-07-24 23:43:41 43
原创 错误码函数
库函数在执行的时候发生了错位,会将一个错误码放在,erron这个变量中,erron是C语言提供的一个库函数,而这个函数,则可以将错误吗,翻译成对应的信息。返回错误码对应的字符串可以打印出来。使用的时候strerror(error)可以在里面添加自定义信息,直接打印。使用:perror(自定义信息)
2023-07-24 21:14:23 51
原创 C语言指针进阶(二)
存放函数指针的数组叫函数指针数组,那么下面哪个是函数指针数组呢?答案是parr1,parr1首先和[ ]结合是数组,然后数组类型是函数指针int (*) ()
2023-07-24 21:01:26 39
原创 C语言指针进阶(一)
在内存中会划分一个个的内存单元,每个单元存在独立的内存编号,这个编号也叫地址。地址在C语言中被称为指针。指针需要存储起来——存储到变量中。这个变量就被称为指针变量。指针的固定大小固定是4/8个大小。指针的类型决定了指针加减整数的步长以及解引用时候的权限。
2023-07-23 00:04:03 54
原创 Linux——环境变量
还有另外一个方法就是,将我们的程序添加到默认的环境变量目录里面去,这样的话我们的二进制文件就直接添加到环境变量目录里面了,这样子的话就不用添加环境变量目录了,因为我们已经将需要运行的程序直接放到环境变量里面了,但是这样子有一个问题,我们很多都只是本次需要添加到环境变量里面的,这个东西是临时的,不需要一直存在,这样子会导致如果环境变量过多的时候很难拿分辨出来哪一个是我们当初添加的环境变量所以不是很推荐。环境变量里面,每一个:。大部分的一般都是处于并发的方式,特殊的服务器会有多个cpu处于并行状态。
2023-06-29 22:45:25 69
原创 Linux——进程
在内核的角度看来进程是担当系统分配资源的实体。操作系统对下管理好软硬件,对上提供一个良好安全的运行环境,对于操作系统来说都是很重要的。管理理念:先描述,在组织。理念——所有共同事务的抽象。对于进程其实是一个,操作系统提供接口(system call),本质上是用·C语言提供的函数.而使用这些函数就叫系统调用。本质上是在调用硬件。
2023-06-29 00:58:44 91
原创 Linux——环境安装与开发工具使用
而Linux下也有对应的应用商店,那么有了应用商店,之后就需要下载,而yum就是一个桥梁,帮助我们下载,把应用下载到Linux系统电脑上。而在每个用户的主目录下,都可以自己建立私有的配置文件,命名为:“.vimrc”。vim可以直接用键盘上的光标来上下左右移动,但正规的vim是用小写英文字母「h」、「j」、「k」、「l」,分别控制光标左、下、上、右移一格。我们使用vim完成我们的代码编辑后,需要对代码进行,预处理——》编译——》——》汇编——》链接(生成可执行文件的过程)。在完成之后可以提交到gitee。
2023-06-27 00:10:00 160
原创 Linux——shell程序及其运行原理
Linux严格意义上来说是一个操作系统,,我们称之位核心"Kernel",但是我们一般人并不能使用它,而是使用外壳程序shell来调用操作系统,与操作系统沟通。技术角度看shell的话他就是一个翻译器,将用户的命令翻译给操作系统,将操作系统的结果处理结果反馈给用户。那么为什么要shell存在呢?因为有时候我们不方便操作系统,对于系统的操作很容易出问题,所以我们找一个中介来帮我们处理。这个中介就是外壳程序?而外壳程序统称为shell,bash是shell外壳程序的一种。
2023-06-24 21:48:12 253 1
原创 Linux——Linux指令
首先我们需要思考一个问题操作系统的操作方式——图形化界面和命令行那个先诞生呢?答案是命令行。为什么呢?在计算机诞生的时候其实是没有鼠标触摸板这些东西的。对于图形化界面的操着方式需要鼠标触摸板以及键盘等方式进行操作,诞生在计算机诞生之初是没有这些东西的。而命令行只需要键盘就可以流畅的操作,因此命令行最先产生。虽然命令行对于现在的我们来说可能操作不方便,但是更贴近系统。在定位上命令行和图形化界面的定位是一样的。
2023-06-23 23:00:20 72
原创 Linux----linux的发展史
这时候不得不提到一个人雷纳斯托瓦兹(Linux之父),年轻的雷纳斯托瓦兹在尝试过后,感觉确实是一个好东西,诞生市面上的操作系统需要收费,这对很多人是不友好的,于是自己也写了一个类似于unix的操作系统Linux并将内核代码开源了出来。Vxx.yy.zz.——xx是主版本,yy是从版本,关于从版本当yy是偶数的时候代表是稳定的可以直接被使用的版本,而如果是奇数的话代表的是测试版,可能有些地方不完善。定位则是企业单位和高校,因为在当时的时代背景下,unix操作系统的售价是很昂贵的,大部分是普通人负担不起的。
2023-06-23 21:14:07 235
原创 C语言字符函数的输入特殊用法——清空字符缓冲区
清空字符缓冲区,当我们在使用scanf函数输入字符的时候,在确认的时候,会按下回车键,但是如果再次输入的时候,因为回车在字符缓冲区,打印的时候会优先读取字符缓冲区的字符,而不是本次输入的字符,因此打印出来的是回车符。在输入第一个之后我们按了回车,也就意味着我们输入了2【回车】我们打印了2,【回车】留在了字符缓冲区,下一个scanf在输入的时候直接优先从字符缓冲区里读取了【回车】进行了打印。在第一次打印后,使用getchar函数将字符缓冲区的多余字符读取出来,清空字符缓冲区。
2023-06-06 00:06:52 576
原创 数据在内存中的存储(二)——浮点数
前言上一篇,我们探讨了整形在数据中的存储,但是除了整形还有浮点数的存在。那么浮点数在内存中是怎么存储的呢?浮点数存储打印示例这一段代码,大家可以猜一下运行结果是什么?我想大部分人的答案应该是9 9.0 9 9.0这样的结果但是答案却不是这样。这才是他的运行结果。那么为什么会有这样的结果呢?
2023-06-01 16:54:52 52
原创 C语言隐式类型转换——整形提升/算术转换
C语言整形总是至少以缺省整形类型的精度来进行的。为了获得这个精度,表达式中的字符和短整型操作数,在使用之前被转换为普通整形,这种转换被称为,整形提升。
2023-05-29 14:36:10 99
原创 C语言——代码调试篇
每一个编程的大佬都是一步一步通过经验的积累,才成为大佬,达到别人无法企及的高度。每一个人都是从编程的新手逐渐走过来的。那么作为一个新手总是不可避免的,回写出有问题含有bug的代码,那么就需要学会调适,发现问题,并解决问题。
2023-05-28 12:23:43 435
原创 C语言——栈帧的创建和销毁
在写代码的时候,有时候在想哪些函数是怎么实现的呢?哪些变量是如何奉陪空间的呢?参数是怎么传递的?在代码上写int =a就分配了内存,那么分配的过程是如何实现的,代码是如何运行的?接下来细说一下这个问题。
2023-05-28 10:01:47 80
原创 数据在内存中的存储(一)
类型 所占字节数char 1 字符存储的时候存储的是ASCII码值,所以也归为整形里面。long 4/8 (long理论上sizeof(long)>=sizeof(int),在大小上没有明确规定,取决于实现环境)
2023-05-27 23:41:53 54
原创 C语言数组篇(一)
在C99之后可以使用变量来定义字符串长度,但是不可以初始化。数组通过下标来访问。通过访问符【】来访问。二位数组初始化,与以为数组类似,不过多了行下表。在内存种的存储也是连续存在的。C语言创建的时候不能用变量才定义数组长度如int arr[i];int arr[10]="ararrar" //以数组形式创建。数组在内存中的使用——数组在内存种连续存放。int arr4[]={1,2,3}//由数组来确定长度。在初始化的时候列行下表可以省略,但是列下标不可以省略。数组的初始化数组的初始化有多种方法。
2023-05-06 22:56:54 37
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人