Linux系统编程常见问题

目录

预处理、编译、汇编和连接

 进程间通信的方式有哪些

 为什么需要进程间通信?

信号产生的原因、处理方式、注册和注销

gdb调试的时候遇到过什么信号

 信号的捕获流程

什么是线程不安全

互斥与同步


预处理、编译、汇编和连接

esc生成iso

  1. 预处理阶段:展开头文件\宏定义,处理条件预编译指令(比如#if、#ifdef、#elif、#else、#endif等),删除所有的注释。生成.i文件
  2. 编译阶段:将预处理完的文本文件hello.i进行一系列的词法分析、语法分析、语义分析和优化。生成.s文件
  3. 汇编阶段:翻译成机器语言指令,将结果保存在一个二进制的.o文件中。
  4. 连接阶段:链接器(ld)将目标文件与所需的库文件链接在一起,生成最终的可执行文件。

 

 进程间通信的方式有哪些

管道、共享内存、消息队列、网络、信号、信号量

管道:就是操作系统内核开辟的一段缓冲区,匿名管道没有标识符,所以只适用于具有亲缘性关系的进程间通信。命名管道的缓冲区以管道文件的形式存在,解决了匿名管道只能在亲缘性关心的进程中使用的问题。

共享内存:是当前在同一台机器上不同进程通信速度最快的方式,在物理内存当中开辟一段空间,不同进程通过页表将物理内存映射到自己的进程虚拟地址空间中,通过操作自己进程的虚拟地址来操作共享内存。

消息队列:消息队列由系统内核维护的链表实现,同时支持按照消息类型先进先出。

信号:信号是软件中断,是进程之间互相传递消息的一种方法,用于通知进程发生了事件,但不能给进程传递任何数据

信号量:本质上是由资源计数器和PCB等待队列组成,因此既能使用信号量进行互斥也能使用信号量进行同步。防止多个进程同时访问公共资源,造成数据混乱

 为什么需要进程间通信?

每个进程通过操作系统将虚拟内存映射到属于自己的真实物理内存当中,因此进程具有独立性,但这种独立性在两个进程之间需要数据交换时就没那么方便了,所以进程间通信本质上是进程和进程之间交换数据的手段。

信号产生的原因、处理方式、注册和注销

 信号的产生分为硬件产生和软件产生,例如ctrl+c产生2号SIGINT信号,ctrl+z产生20号SIGSTP信号,以及kill函数 向指定进程发送信号、raise函数向自身发送信号。

gdb调试的时候遇到过什么信号

Double free产生6号SIGABRT信号,(解引用空指针,内存访问越界、栈溢出}产生11号SIGSEGV信号(段错误),管道破裂产生13号SIGPIPE信号,除0错误产生8号SIGFPE信号

信号的处理方式包括:默认处理方式、忽略处理方式和自定义处理方式。其中默认处理方式是操作系统当中已经定义好的每个信号对应的处理方式;忽略处理方式表示对该信号忽略处理,例如僵尸进程的产生原因就是子进程先于父进程退出时给父进程发送SIGCHLD信号,父进程对于这个信号正是忽略处理的,因此导致没有进程回首子进程的退出信息,导致僵尸进程的产生。而自定义处理方式则是程序员可以更改信号的处理方式,定义一个函数,当进程收到该信号的时候,去调用自定义的信号处理函数。(每个task_struct结构体下都有一个sighand_struct结构体指针,该结构体维护一个包含信号处理方式的结构体数组,对应各信号的处理信息,通过修改数组中结构体的内容修改信号处理方式。)

一个进程收到一个信号,这个过程就称为信号的注册,操作系统内部会更改sig位图并将sigqueue节点添加到sigqueue队列中。当同时来了两个相同信号时,不同种类的信号之间的注册也有区别,1~31号为非实时信号,只会添加一次节点到sigqueue队列,可以理解为只注册一次;而34~64为实时信号,会添加两次节点到sigqueue队列,注册两次。

非实时信号和实时信号的注销也有所不同,非实时信号将对应的sig位图中的比特位置零并将信号对应的节点出队完成注销。而实时信号先将对应的信号节点出队,然后判断sigqueue队列中还有相同信号的节点吗,如果有则比特位不变,如果没有则比特位置0。

信号的捕获流程

用户态系统调用等原因进入内核态,处理完之后,返回用户态之前会执行do_signal函数,判断当前进程有没有收到信号。如果没收到信号,do_signal完毕返回用户态。如果发现有信号注册,先判断信号是否阻塞,如果阻塞则不处理,如果不阻塞,则去处理信号。处理信号也有两种情况,如果信号处理方式没有被程序员自定义则直接在内核态处理,处理完所有信号后,执行sys_sigretrun()返回用户态。如果信号处理方式被自定义了,这返回用户态执行自定义处理函数,处理完返回内核态处理之后的信号,直到信号也处理完了,执行sys_sigretrun()返回用户态。

什么是线程不安全

 程序执行的结果出现二义性行为,例如多个线程对同一个变量进行加或减操作,可能会发生一个线程从内存中读取变量值到寄存器时,线程被切换,另一个线程被调度执行从内存中拿到相同的变量值进行操作。当之后前者线程被调度时,直接从寄存器中拿值操作并将结果写回内存。就会出现变量分别被两个线程操作了一次减一,而结果只减了一次1的现象。

互斥与同步

当多个线程能够同时访问到临界资源的时候,有可能会导致线程执行的结果产生二义性。而互斥就是要保证多个线程在访问同一个临界资源,执行临界区代码的时候,控制访问时序。让一个线程独占临界资源执行完,再让另外一个独占执行。

同步:保证线程在互斥的基础上,对临界资源访问的合理性。(例如,一个进程在变量>0的时候加锁-1,如果这个变量一直不>0,不能让这个进程循环一直判断,会非常浪费cpu资源,此时应该让他等待,如果变量>0了,同步通知这个线程)

  • 24
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值