常见操作系统面试题

进程线程的区别:
1. 进程是资源的分配和调度的一个独立单元,而线程是CPU调度的本单元
2. 同一个进程可以包含多个线程,并且线程共享整个进程的资源(寄存器,堆栈,上下文)一个进程至少包含一个线程。
3. 进程的创建调用fork或者 vfork,而线程的创建调用pthread_create(),进程结束之后他所有的线程销毁都会销毁,而线程的结束不会影响该线程中其他的线程结束
4. 线程是轻量级进程,他的创建和销毁所需要的时间比进程小很多,所有的操作系统中的执行功能都是创建线程完成的
5. 线程中执行时一般都要进行同步互斥,因为他们共享同一进程的所有资源
6. 线程有自己的私有属性TCB,线程ID,寄存器,硬件上下文, 而进程也有自己的私有属性进程控制块PCB,这些私有属性是不被共享的,用来表示一个进程或者一个进程的标志。

总结:概念;创建,销毁;资源共享的特点:线程的私有属性:线程ID,寄存器,硬件上下文

什么是死锁?产生死锁的原因,怎么处理死锁??

  • 相互等待资源而产生的一种僵持状态,如果没有外力的敢于将一直持续这个状态
  • 原因:系统资源不足,相互竞争资源,请求资源顺序不当。例如:当一个锁资源已经被A拿到,还没有释放,这个时候B又来申请锁,就会产生死锁。当A已经获取了锁资源,又尝试获取锁。多个锁,多个人申请锁,更加可能产生死锁
  • 死锁的必要条件:互斥,不可抢占,循环等待,请求和保持
  • 解决:因为互斥是不可以改变的,所以只能破坏其他的三个条件中的一个来解除死锁,方法:剥夺资源,杀死其中一个线程

进程的几种状态:RSDTZ

  • run(运行状态):正在运行的进程火灾等待队列中等待的进程,等待的进程只要一得到CPU就可以运行
  • sleep(可中断睡眠状态):相当于阻塞或在等待的状态
  • D(停止状态):在磁盘上的进程
  • T(停止状态):这种状态无法直观的看见,因为进程停止之后就释放了资源,所以不会留在Linux中
  • Z(僵尸状态):子进程先退出,但是父进程没有调用wait或者waitpid来回首紫禁城的资源,所以子进程就变成了僵尸进程。如果父进程结束后仍然没有回收子进程的资源,那么僵尸进程则被1号进程(init)回收

进程间通信方式:


- 管道:(匿名管道(pipe 具有亲缘关系的进程之间进行通信)),命名管道:(mkfifo),可以是任意之间的进程。
- 消息对列:基于消息的,用于无亲缘关系的进程之间的进程间通信,(msgget/msgsend/msgrecv/msgctl) 能够应用于任意的进程之间;双向通信,全双工; 面向数据块;内置了同步互斥机制; 生命周期随内核
- 信号量:相当于一把互斥锁,通过P/V操作来进行同步互斥,msgget,semop,semctl; 1、能够应用于任意进程之间;2、双向通信,每一个进程都既可以读,也可以写 3、 没有面向字节流或者面向数据块的概念,随机访问内存中的数据/4、 没有同步与互斥;(需要的话,就要求我们自己实现同步互斥——可以使用信号量来实现)5、生命周期随内核
- 共享内存:是进程间通信速度最快的,所以经常是用信号量和互斥锁来实现同步:shmget,shmat,shmdt,shmctl;P(-1)V(+1)

什么是虚拟内存:

解析:是将进程部分装入内存中,从而实现一个很大的程序能在一个比他小的内存中运行,他的主要实现是靠程序的换进换出来实现的,因为内存中0~3G是用户使用,3~4G才是内存使用,通过内存映射来实现来进项逻辑地址到物理地址的映射
虚拟地址,逻辑地址,线性地址,物理地址的区别:
分段机制把一个逻辑地址转换为线性地址;接着,分页机制把一个线性地址转换为物理地址
- 虚拟地址:虚拟内存引射出来的地址
- 逻辑地址:程序的段加偏移量形成的,C/C++程序中取地址出来的之地这就是逻辑地址
- 线性地址:是逻辑地址到物理地址的中间层,只有启动分页机制的时候才有线性地址
- 如果没有分页机制,那么线性地址就是物理地址
- 物理地址:是内存中实实在在存在的硬件地址
- 逻辑地址(启动分段)—》线性地址(启动分页)–》物理地址

TCP和UDP特点

各层对应的协议

这里写图片描述
应用层:DNS,URL,HTML,HTTP
TLS/SSL,SMTP,POP,IMAP,
MIME,TELNET,SSH,FTP
SNMP,MIB,SIP,RTP,LDAP
传输层协议:TCP,UDP,UDP-Lite,SCTP,DCCP
网络层:ARP,IP,ICMP
数据链路层:网卡层
物理层:硬件

TCP和UDP比较:

● 基于连接 无连接
● 面向字节流 面向数据报
● tcp要求系统资源比较多,UDP 较少
● udp程序结构更简单
● TCP保证数据正确性(可靠传输);UDP可能会丢包
● TCP保证数据的顺序,(分包,编序号);udp不能保证

UDP应用场景:

● 面向数据报方式
● 网络数据大多为短消息
● 拥有大量的 client
● 对数据安全性无特殊要求
● 网络负担非常重,但是对响应速度要求高
具体网络编程时的参数不同:
● socket套接字:udp创建套接字,第二个参数是SOCK_STREAM (就是udp的意思);而tcp第二个参数是 SOCK_DGRAM ;他们第一个参数都是AF_INET表示ipv4协议
● UDP:server不需要调用listen和accept(没有三次握手四次挥手);
● TCP:地址信息在connect/recvfrom函数中每次都需要制定地址信息
● UDP:shutdown函数无效

socket的参数:

SOCK_STREAM:这种是TCP协议的网络通讯,他是面向连接的。每次收发数据之前都要先connect先创建连接,双向的。(三次握手四次挥手过程)。任何一方都可以接收数据。因为协议的某些保障,所以他传输数据是可靠的,安全的,有序的。每个包按照自己的顺序发送到接收方
SOCK_DGRAM:是UDP的通讯方式,他是无连接的,不可靠的,因为通讯双方并不知道彼此是否接收到了数据。数据是否正常。任何一方建立一个socket之后就可以用sendto发送数据,也可以用recvfrom来接收数据。他是不关心对方是不是在,是不是接收到了数据,接收到的数据是否正确,没有那么多条件,自然他的传输是比较快的。

网络编程的区别:

TCP:
创建server端:

● 创建套接字,注意参数的传递
● 绑定IP地址,端口信息到socket上,bind
● 开始监听,listen
● 接收客户端上来的连接,accept
● 收发数据,用函数send() 和recv();我们一般用read()和write()
● 关闭网络连接
● 关闭监听

创建client端:

● 创建socket,
● 设置要连接的端口(sockaddr)设置协议(IPV4)AF_INET:sockaddr.sin_family; sockaddr.sin_addr.s_addr = inet_addr(argv[1]):将网络字节序以点分十进制的方式转换为二进制(就是那个IP地址) sockaddr.sin_port = htons(atoi(argv[2])):(9090)从主机序转换为网络字节序
inet_ntoa:函数以字节顺序将Internet主机地址转换为IPv4点十进制记数法中的字符串
ntohs:函数将无符号短整数netshort由网络字节为主机字节顺序
● 连接服务器,connect
● 收发数据,用read()和write()
● 关闭网络连接(关闭套接字),这里套接字就相当于是一个文件描述符,直接close()就好

UDP:
创建server端:

● 创建socket(SOCK_DGRAM)
● 绑定端口号 bind
● 循环接收数据,recvfrom
● 关闭套接字

创建client端:

● 创建套接字
● 设置socket属性 IP ,端口号,网络字节序(sockaddr)
● 发送数据,sendto
● 关闭网络连接

原文地址:https://www.cnblogs.com/chan0311/p/9427313.html