作业1->使用文件IO完成,将源文件中的所有内容进行加密(大小写互相转换)后写入目标文件,源文件内容不变
#include<myhead.h>
int main(int argc, const char *argv[])
{
if(argc!=3) //提示输入错误
{
write(2,"open error\n",sizeof("open error\n"));
return -1;
}
int fd1=open(argv[1],O_RDONLY); //打开源文件 只读
if(fd1==-1)
{
perror("open error1");
return -1;
}
int fd2=open(argv[2],O_WRONLY|O_CREAT|O_TRUNC,0664); //打开目标文件
if(fd2==-1)
{
perror("open error2");
return -1;
}
char buf[20]=""; //定义搬运工
char buff=0; //读取buf里的字符
// 读取源文件并转换大小写
while (1)
{
int scr = read(fd1, buf, sizeof(buf)); //定义返回值容器接受read函数返回值
if(scr==0) //无可接受的内容时停止循环
{
break;
}
for (int i = 0; i < sizeof(buf);i++) //小搬运工读取字符串内容
{
buff = buf[i];
if (buff>='A'&&buff<='Z')
{
buf[i] = buff+32; //判断大小写字母 相互转换
} else if (buff>='a'&&buff<='z')
{
buf[i] = buff-32;
}
// 非字母字符保持不变
}
// 写入目标文件
write(fd2, buf, scr);
}
//关闭俩文件
close(fd1);
close(fd2);
return 0;
}
作业2->查资料了解以下概念:
并发和并行的区别
-
定义:
- 并发:指的是在多任务环境中,多个任务在宏观上同时执行,但在微观上是交替执行的。并发不要求多个任务一定在多个处理器上同时执行,它可以在单个处理器上通过时间分片来实现。
- 并行:指的是多个任务在多个处理器上同时执行。并行要求有多个物理或逻辑处理器,每个处理器执行不同的任务或任务的一部分。
-
处理器使用:
- 并发可以在单核处理器上实现,通过操作系统调度任务来给用户一种多个任务同时进行的错觉。
- 并行需要多核处理器或多台机器,每个核心或机器可以独立执行任务。
-
目的:
- 并发主要目的是提高资源利用率和系统吞吐量,通过允许多个任务交替执行来减少等待时间。
- 并行的主要目的是加速计算过程,通过同时执行多个任务来缩短总体完成时间。
-
应用场景:
- 并发常见于操作系统中的任务调度,例如,在单核计算机上运行多个应用程序。
- 并行常见于高性能计算、图形渲染、大数据分析等领域,这些领域需要处理大量数据或复杂计算。
-
实现方式:
- 并发可以通过多线程、进程、事件驱动编程等技术实现。
- 并行可以通过多线程、分布式计算、GPU加速等技术实现。
-
性能影响:
- 并发可以提高单个处理器的利用率,但可能不会减少任务的绝对执行时间。
- 并行可以减少任务的绝对执行时间,因为多个任务可以同时进行。
-
复杂性:
- 并发编程需要处理任务调度、同步、死锁等问题。
- 并行编程除了需要处理并发编程的问题外,还需要考虑数据分割、通信开销、负载平衡等问题。
并发和并行都可以提高程序的执行效率,但它们的实现方式、应用场景和关注点有所不同。并发更侧重于任务的宏观同时性,而并行则侧重于任务的微观同时性。
什么是进程
它指的是在操作系统中正在执行的一个程序的实例。进程是操作系统进行资源分配和调度的一个单位
-
程序与数据的集合:进程由程序代码、程序计数器、寄存器、堆栈、堆和栈等组成。这些元素共同定义了程序的执行状态。
-
独立的内存空间:每个进程都有自己独立的地址空间。这意味着进程间的内存是隔离的,一个进程不能直接访问另一个进程的内存空间。
-
系统资源的请求者:进程可以请求操作系统分配给它所需的资源,如CPU时间、内存、I/O设备等
进程和程序的区别
-
- 程序:程序是一组指令的集合,这些指令被编写来完成特定的任务。程序通常存储在磁盘上,是静态的,不包含执行状态信息。
- 进程:进程是一个程序的执行实例,它包含了程序代码、程序计数器、寄存器、堆栈、堆和栈等。进程是动态的,包含了程序执行时的状态信息。
-
存储位置:
- 程序存储在磁盘上,是一个静态的文件。
- 进程存在于内存中,是一个活动的实体。
-
执行:
- 程序本身不执行任何操作,它需要被加载到内存中并由操作系统创建一个进程来执行。
- 进程是程序的运行实体,它按照程序的指令执行操作。
-
独立性:
- 程序是独立于其他程序的,它不包含执行状态或资源分配信息。
- 每个进程都有自己独立的地址空间和系统资源,如CPU时间、内存、I/O设备等。
-
生命周期:
- 程序的生命周期与操作系统无关,它是一个静态的文件,直到被加载到内存中。
- 进程有生命周期,包括创建、执行、等待、阻塞和终止等状态。
进程的状态有哪些
-
新建(New or Initialization):
进程正在被创建。操作系统正在为新进程分配资源,如内存空间和进程控制块。 -
就绪(Ready):
进程已准备好执行,但正在等待分配CPU时间。它已经分配了所有必要的资源,只等待CPU来执行。 -
运行(Running):
进程正在获得CPU时间并执行指令。在单核系统中,只有一个进程处于此状态;在多核系统中,可以有多个进程同时处于运行状态。 -
阻塞(Blocked or Waiting):
进程正在等待某个事件的发生,如I/O操作完成、接收到信号或获得一个锁。在等待期间,它不会消耗CPU资源。 -
终止(Terminated):
进程已经完成执行或被操作系统强制终止。它的资源将被回收,如内存空间被释放。 -
挂起(Suspended or Stopped):
进程的执行被操作系统或用户暂时挂起。它可以是部分挂起,即进程的代码仍在内存中,但不会执行;或者是完全挂起,即进程的代码从内存中移除。 -
僵尸(Zombie):
进程已经完成执行,但其父进程尚未读取其退出状态。这种状态下的进程占用系统资源,但不再执行代码。 -
交换(Swapped):
在内存紧张的情况下,操作系统可能会将进程的部分或全部内容从内存交换到磁盘上,这个过程称为交换或页面置换。 -
创建挂起(Creation Suspended):
进程被创建,但由于某些原因(如资源限制),它被操作系统挂起,等待资源可用。 -
唤醒(Awakened):
进程从阻塞状态变为就绪状态,等待操作系统将其调度为运行状态。
系统中的多个进程的调度机制有哪些
-
先来先服务(FCFS, First-Come, First-Served):
按照进程到达的顺序进行调度,最简单的调度算法。 -
短作业优先(SJF, Shortest Job First):
优先调度估计执行时间最短的进程,可以是抢占式或非抢占式。 -
优先级调度(Priority Scheduling):
根据进程的优先级进行调度,高优先级的进程先执行。 -
时间片轮转(RR, Round Robin):
每个进程被分配一个固定的时间片,进程轮流执行其时间片。 -
多级队列(MLQ, Multi-Level Queue):
将进程分为不同的类别或优先级,并为每个类别维护一个队列,每个队列有自己的调度算法。 -
多级反馈队列(MFQ, Multi-Level Feedback Queue):
结合了时间片轮转和多级队列的特点,允许进程在不同优先级的队列之间移动。 -
基于比例的调度(PBS, Proportional Share Scheduling):
根据进程的权重分配CPU时间,确保公平性。 -
实时调度(Real-Time Scheduling):
用于实时系统,确保高优先级的进程能够及时响应。 -
完全公平调度(CFS, Completely Fair Scheduler):
现代Unix系统(如Linux)使用的调度算法,它为每个进程分配CPU时间份额,保证公平性。 -
彩票调度(Lottery Scheduling):
每个进程获得一定数量的彩票,调度时随机选择彩票,持有彩票多的进程更可能被选中。 -
合作式多任务(Cooperative Multitasking):
进程必须显式地让出CPU给其他进程,没有抢占机制。 -
抢占式多任务(Preemptive Multitasking):
操作系统可以中断正在运行的进程,将CPU分配给另一个进程。
3->思维导图
面试题:
结构体的字节对齐原则
字节对齐的原则有两个:1、结构体中的每个成员在分配内存时,要以数据类型对齐一次
2、所有成员分配内存结束后,整体要对齐一次:
32位系统与其中最大字节成员和4字节中的小者对齐
64位系统与其中最大字节成员和8字节中的小者对齐
如何设置结构体两字节对齐
在宏定义部分使用#pragma pack(push,2)来设置结构体字节对齐
链表,队列,栈的区别
链表是链式存储的线性表,其中存储数据元素的地址不一定连续,同时数据元素之间存在一对一的关系,可以在堆区申请空间从而能够有效地利用零散空间;可以于端点或是中间位置处理数据元素
队列和栈是功能受限的线性表,只能在端点操作;
栈只能从同一段插入和删除,先进的后出,后进的先出;
队列只能从一端输入,另一端输出,先进的先出,后进的后出
标准IO 和文件IO区别
IO就是程序与外部设备进行信息交换的过程
标准IO是调用封装好的相关库函数,来实现数据的输入输出
文件IO是调用系统(内核)提供的相关函数,来实现数据的输入输出;
标准IO操作的是文件指针,文件IO操作的是文件描述符
标准IO有缓冲区,文件IO没有缓冲区
什么是回调函数
回调函数是一种编程模式,通常在异步编程中使用。它是一种特殊的函数,作为参数传递给另一个函数,然后在某个时间点被调用。这种模式允许程序在完成某些操作后执行额外的代码,而不必阻塞主线程。
gcc编译完整流程
1、预处理:展开头文件,替换宏定义,删除注释;2、编译:检查语法错误,有错报错,没错继续运行生成汇编文件;3、汇编:生成一个不可执行的二进制文件;4、链接:链接库函数,最终生成可执行二进制文件。
结构体和共用体的区别
结构体和共用体都是构造数据类型,都是由相同或不同类型构成的集合
共用体集合中的成员共享同一块空间,结构体成员遵循字节对齐原则申请空间;
共用体成员变量一般不作为函数参数传递,结构体成员变量可以作为参数传递
形参和实参的区别
形参是函数定义过程中的参数,用于接收传递给函数的值
形参是函数内部的局部变量,于函数被调用时被创建,于函数执行完毕后被销毁;
实参是在调用函数时实际传递给函数的值或变量
实参可以时常量、变量、表达式或者其他仍和可以计算出值的实体;
当函数被调用时,实参的值被复制或传递给对应的形参
作用域:形参时函数定义的一部分,存在于函数的内部;实参是函数调用的一部分,存在于函数外部;
生命周期:形参的生命周期仅限于函数的执行期间;实参的生命周期取决于它们本身的类型和作用域;
数据传递:形参接收实参的值,但它们之间没有直接的联系。实参的值被复制到形参中,函数内部对形参的修改往往不会影响到实参;
数量:在函数定义时,形参的数量和类型必须与函数调用时提供的实参数量和类型一致