[讨论] 《Rust实战》读书笔记——第12章,信号、中断和异常

nemon   2024-6-19 20:45 楼主

作者延续上一章的风格,demo级的介绍,帮助理解概念入门。

12_01.png

说实话,真没啥好解释的,中断就是程序跑着跑着,突然CPU接到了什么神谕,然后就对程序说“你站在此地不要动,我去买几个橘子”,直到cpu忙完了,程序才敢接着跑。

可以引入asm特性,像c一样嵌入汇编直接调软中断。

 

信号是操作系统特性,举的例子是SIGSTOP是暂停执行SIGCONT是继续执行。

可以用libc的signal、raise来自定义信号处理方式(libc::signal(信号名, 处理函数);)、发出信号。

 

本书最后一个例子加进了一个知识点——rust支持setjmp、longjmp这种操作:

#![feature(link_llvm_intrinsics)]
#![allow(non_camel_case_types)]
#![cfg(not(windows))]

use libc::{
  SIGALRM, SIGHUP, SIGQUIT, SIGTERM, SIGUSR1,
};
use std::mem;

const JMP_BUF_WIDTH: usize =
  mem::size_of::<usize>() * 8;
type jmp_buf = [i8; JMP_BUF_WIDTH];

static mut SHUT_DOWN: bool = false;
static mut RETURN_HERE: jmp_buf = [0; JMP_BUF_WIDTH];
const MOCK_SIGNAL_AT: usize = 3;

extern "C" {
  #[link_name = "llvm.eh.sjlj.setjmp"]
  pub fn setjmp(_: *mut i8) -> i32;

  #[link_name = "llvm.eh.sjlj.longjmp"]
  pub fn longjmp(_: *mut i8);
}

#[inline]  
fn ptr_to_jmp_buf() -> *mut i8 {
  unsafe { &RETURN_HERE as *const i8 as *mut i8 }
}

#[inline]    
fn return_early() {
  let franken_pointer = ptr_to_jmp_buf();
  unsafe { longjmp(franken_pointer) }; 
}

fn register_signal_handler() {
  unsafe {
    libc::signal(SIGUSR1, handle_signals as usize);
  }
}

#[allow(dead_code)]
fn handle_signals(sig: i32) {
  register_signal_handler();

  let should_shut_down = match sig {
    SIGHUP => false,
    SIGALRM => false,
    SIGTERM => true,
    SIGQUIT => true,
    SIGUSR1 => true,
    _ => false,
  };

  unsafe {
    SHUT_DOWN = should_shut_down;
  }

  return_early();
}

fn print_depth(depth: usize) {
  for _ in 0..depth {
    print!("#");
  }
  println!();
}

fn dive(depth: usize, max_depth: usize) {
  unsafe {
    if SHUT_DOWN {
      println!("!");
      return;
    }
  }
  print_depth(depth);

  if depth >= max_depth {
    return;
  } else if depth == MOCK_SIGNAL_AT {
    unsafe {
      libc::raise(SIGUSR1);
    }
  } else {
    dive(depth + 1, max_depth);
  }
  print_depth(depth);
}

fn main() {
  const JUMP_SET: i32 = 0;

  register_signal_handler();

  let return_point = ptr_to_jmp_buf();
  let rc = unsafe { setjmp(return_point) };
  if rc == JUMP_SET {
    dive(0, 10);
  } else {
    println!("early return!");
  }

  println!("finishing!")
}

就是这些。

 

回复评论 (2)

中断、信号、异常是cpu与系统外设通信的重要手段,理解这几个概念对有效控制外围硬件设备非常重要

点赞  2024-6-20 06:01

rust干这些活太别扭了,能干,但是不好干。

默认摸鱼,再摸鱼。2022、9、28
点赞  2024-6-25 11:56
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复