1.标准IO和文件IO的区别
标准I/O | 文件IO | |
概念 | C库中定义的一组用于输入输出的函数 | 系统中定义的一组用于输入输出的函数 |
特点 | 1)有缓冲机制,减少系统调用 2)围绕文件流进行操作 3)默认打开三个文件流,stdin、stdout、stderr 4)只能对普通文件进行操作 | 1)无缓冲机制,每次都要系统调用 2)围绕文件描述符进行操作 3)默认打开3个文件描述符,0,1,2 4)可以对任意类型文件操作,目录除外 |
函数 | 打开文件:fopen freopen 关闭文件:fclose 文件读写:fgetc fputc fgets fputs fread fwrite 文件定位操作:fseek ftell rewind | 打开文件:open 关闭文件:close 文件读写:read write 文件定位操作:lseek |
diff 文件一 文件二:对比两个文件有无不同
2.静态库和动态库的区别
静态库和动态库,本质区别是代码被载入时刻不同。
1) 静态库在程序编译时会被连接到目标代码中。
优点:程序运行时将不再需要该静态库;运行时无需加载库,运行速度更快。
缺点:静态库中的代码复制到了程序中,因此体积较大;
静态库升级后,程序需要重新编译链接
2) 动态库是在程序运行时才被载入代码中。
优点:程序在执行时加载动态库,代码体积小;程序升级更简单;
不同应用程序如果调用相同的库,那么在内存里只需要有一份该共享库的实例。
缺点:运行时还需要动态库的存在,移植性较差
3.怎么创建进程
pid_t pid=fork();
4.什么是守护进程
守护进程是后台进程;生命周期比较长,从系统启动时开启,系统关闭时结束;它是脱离控制终端且周期执行的进程。
步骤:
1) 创建子进程,父进程退出
让子进程变成孤儿进程,成为后台进程;fork()
2) 在子进程中创建新会话
让子进程成为会话组组长,为了让子进程完全脱离终端;setsid()
3) 改变进程运行路径为根目录
原因进程运行的路径不能被删除或卸载;chdir("/")
4) 重设文件权限掩码
目的:增大进程创建文件时权限,提高灵活性;umask(0)
5) 关闭文件描述符
将不需要的文件关闭;close()
5.什么是僵尸进程?什么是孤儿进程?
1)子进程几乎拷贝了父进程的全部内容。包括代码、数据、系统数据段中的pc值、栈中的数据、父进程中打开的文件等;但它们的PID、PPID是不同的。
2)父子进程有独立的地址空间,互不影响;当在相应的进程中改变全局变量、静态变量,都互不影响。
3)若父进程先结束,子进程成为孤儿进程,被init进程收养,子进程变成后台进程。
4)若子进程先结束,父进程如果没有及时回收,子进程变成僵尸进程(要避免僵尸进程产生)。进程已经终止运行,但还占用系统资源
6.时间片了解么?
在宏观上:我们可以同时打开多个应用程序,每个程du序并行不悖,同时运行。
但是在微观上:由于只有一个CPU,一次只能处理程序要求的一部分,如何处理公平,一种方法就是引入时间片,每个程序轮流执行。
时间片即CPU分配给各个程序的时间,每个线程被分配一个时间段,称作它的时间片,即该进程允许运行的时间,使各个程序从表面上看是同时进行的。如果在时间片结束时进程还在运行,则CPU将被剥夺并分配给另一个进程。如果进程在时间片结束前阻塞或结束,则CPU当即进行切换。而不会造成CPU资源浪费。在宏观上:我们可以同时打开多个应用程序,每个程序并行不悖,同时运行。但在微观上:由于只有一个CPU,一次只能处理程序要求的一部分,如何处理公平,一种方法就是引入时间片,每个程序轮流执行。
7.进程和线程区别?
共性:都为操作系统提供了并发执行能力
不同点:
调度和资源:线程是系统调度的最小单位,进程是资源分配的最小单位
地址空间方面:同一个进程创建的多个线程共享进程的资源;进程的地址空间相互独立
通信方面:线程通信相对简单,只需要通过全局变量可以实现,但是需要考虑临界资源访问的问题;进程通信比较复杂,需要借助进程间的通信机制(借助3g-4g内核空间)
安全性方面:线程安全性差一些,当进程结束时会导致所有线程退出;进程相对安全
临界资源:一次仅允许一个线程使用共享资源
8.线程的同步怎么实现
通过信号量、互斥锁、条件变量
信号量:通过信号量实现同步操作;由信号量来决定线程是继续运行还是阻塞等待
信号量代表某一类资源,其值表示系统中该资源的数量,信号量值>0,表示有资源可以用,可以申请到资源,继续执行程序,信号量值=0,表示没有资源可以用,无法申请到资源,阻塞。
信号量是一个受保护的变量,只能通过三种操作来访问:初始化sem_init、P操作(申请资源)sem_wait、V操作(释放资源)sem_post
信号量的值为非负整数
1.初始化信号量 int sem_init(sem_t *sem, int pshared, unsigned int value)
2. 申请资源 int sem_wait(sem_t *sem)
3. 释放资源 int sem_post(sem_t *sem)
9.线程的互斥怎么实现
互斥:多个线程在访问临界资源时,同一时间只能一个线程访问
互斥锁:通过互斥锁可以实现互斥机制,主要用来保护临界资源,每个临界资源都由一个互斥锁来保护,线程必须先获得互斥锁才能访问临界资源,访问完资源后释放该锁。如果无法获得锁,线程会阻塞直到获得锁为止。
1. 初始化锁,pthread_mutex_init
2. 申请互斥锁 pthread_mutex_lock
3. 释放互斥锁 pthread_mutex_unlock
4. 销毁互斥锁 pthread_mutex_destroy
10.进程间通信方式有哪些?哪种效率最高
线程通信:全局变量
1. 早期通信:无名管道、有名管道、信号
2. system V IPC:共享内存、消息队列、信号灯集
3. BSD:socket通信
共享内存是一种最为高效的进程间通信方式,进程可以直接读写内存,而不需要任何数据的拷贝
11.通信方式的优缺点对比
【1】无名管道
1. 只能用于具有亲缘关系的进程间通信
2. 半双工通信方式,有固定的读端和写端
半双工:可以双向通信,但是同一时刻只能单向传输信息。
全双工:可以双向同时通信。
单工:单向传送信息。
3. 无名管道可以看作特殊的文件,对它的读写可以使用文件IO操作read、write
4. 无名管道基于文件描述符进行操作,当一个管道建立,它会创建两个文件描述符
fd[0]固定的读管道,fd[1]固定的写管道
【2】有名管道
1. 特点:***
1. 有名管道可以使互不相干进程进行通信
2. 有名管道可以通过路径名指出,在文件系统中可见,但数据内容存放在内存中。
3. 通过文件IO进行操作,
4. 遵循先进先出原则
5. 不支持lseek()操作。
【3】共享内存
1)共享内存是一种最为高效的进程间通信方式,进程可以直接读写内存,而不需要任何数据的拷贝
2)为了在多个进程间交换信息,内核专门留出了一块内存区,可以由需要访问的进程将其映射到自己的私有地址空间
3)进程就可以直接读写这一内存区而不需要进行数据的拷贝,从而大大提高的效率。
4)由于多个进程共享一段内存,因此也需要依靠某种同步机制,如互斥锁和信号量等
【4】消息队列
消息队列是IPC对象的一种
消息队列由消息队列ID来唯一标识
消息队列就是一个消息的列表。用户可以在消息队列中添加消息、读取消息等。
消息队列可以按照类型来发送(添加)/接收(读取)消息
12.有名管道和无名管道的区别?
**【3】有名管道无名管道对比
无名管道 | 有名管道 | |
使用场景 | 亲缘关系 | 互不相干 |
特点 | 半双工通信 具有固定的读端fd[0]和写端fd[1] 看作特殊文件,文件IO操作 | 半双工通信 先进先出,不支持lseek操作 通过文件IO进行操作,在系统中可见,但数据存放在内存中 |
函数 | pipe() 可直接进行读写操作 | mkfifo() 要先open,在进行读写操作 |
读写特性 | 当管道中无数据,读阻塞 当管道中写满数据,写阻塞 读端关闭,继续写会导致管道破裂 | 只写方式写阻塞,直到另一个进程将读打开 只读方式读阻塞,直到另一个进程将写打开 可读可写,若管道中无数据,读阻塞 |
13.共享内存的实现方式
1.创建key值 ftok
2. 创建或打开共享内存 shmget
3. 映射共享内存到用户空间 shmat
4. 撤销映射shmdt
5. 删除共享内存shmctl
命令
ipcs -m :查看系统中共享内存
ipcrm -m shmid:删除shmid号的共享内存
14.消息队列的实现方式
1. 创建key值ftok
2. 创建或者打开消息队列 msgget
3. 添加消息:按照类型将消息添加到已经代开的消息队列末尾msgsnd
4. 读取消息:可以按照类型读取消息msgrcv
5. 删除消息队列msgctl
命令
ipcs -q:查看消息队列
ipcrm -q msgid:删除编号为msgid的消息队列
15.fork和vfork区别
1.fork(): 子进程拷贝父进程的数据段,代码段
vfork(): 子进程与父进程共享数据段
2.fork(): 父子进程执行次序不确定
vfork(): 保证子进程先运行,在调用exec()或exit()之前,与父进程数据共享,在exec()或exit()调用之后,父进程才能运行
3. 在使用vfork函数在调用exec()或exit()之前,子进程依赖于父进程的进一步动作,将会导致死锁。
16.线程的死锁,怎么避免?
死锁产生的四个必要条件:
1、互斥使用,即当资源被一个线程使用(占有)时,别的线程不能使用
2、不可抢占,资源请求者不能强制从资源占有者手中夺取资源,资源只能由资源占有者主动释放。
3、请求和保持,即当资源请求者在请求其他的资源的同时保持对原有资源的占有。
4、循环等待,即存在一个等待队列:P1占有P2的资源,P2占有P3的资源,P3占有P1的资源。这样就形成了一个等待环路。
注意:当上述四个条件都成立的时候,便形成死锁。当然,死锁的情况下如果打破上述任何一个条件,便可让死锁消失。