boolget_signal(struct ksignal *ksig) ... signr = dequeue_signal(current, ¤t->blocked, &ksig->info); ... if (ka->sa.sa_handler == SIG_IGN) /* Do nothing. */ continue; if (ka->sa.sa_handler != SIG_DFL) { /* Run the handler. */ ksig->ka = *ka;
if (ka->sa.sa_flags & SA_ONESHOT) ka->sa.sa_handler = SIG_DFL;
break; /* will return non-zero "signr" value */ }
若用户没有绑定signal handler,则使用内核默认处理方式
若signal在coredump信号列表定义内,则会产生coredump
1 2 3 4 5 6 7 8 9 10 11 12 13 14
if (sig_kernel_coredump(signr)) { if (print_fatal_signals) print_fatal_signal(ksig->info.si_signo); proc_coredump_connector(current); /* * If it was able to dump core, this kills all * other threads in the group and synchronizes with * their demise. If we lost the race with another * thread getting here, it set group_exit_code * first and our do_group_exit call below will use * that value and ignore the one we pass it. */ do_coredump(&ksig->info); }
/* Send signal which possibly calls a user handler. */ if (stage == 1) { /* This stage is special: we must allow repeated calls of `abort' when a user defined handler for SIGABRT is installed. This is risky since the `raise' implementation might also fail but I don't see another possibility. */ int save_stage = stage; stage = 0; __libc_lock_unlock_recursive (lock); raise (SIGABRT); __libc_lock_lock_recursive (lock); stage = save_stage + 1; } /* There was a handler installed. Now remove it. */ if (stage == 2) { ++stage; memset (&act, '\0', sizeof (struct sigaction)); act.sa_handler = SIG_DFL; __sigfillset (&act.sa_mask); act.sa_flags = 0; __sigaction (SIGABRT, &act, NULL); } /* Try again. */ if (stage == 3) { ++stage; raise (SIGABRT); }
函数式编程中的函数不是指计算机中的函数,而是数学中的函数,即自变量的映射f(x)。一个函数的值仅决定于函数参数的值,不依赖其他状态。比如sqrt(x)计算x的平方根,只要x不变,不论什么时候调用,调用几次,值都不变,所以纯函数式编程中,变量是代数中的变量,即一个值的名称,变量的值是不可变的,比如x = x + 1在数学代数里,这个等式为假,由于变量值是不可变的,对于值的操作并不是修改原来的值,而是修改新产生的值,原来的值保持不变
char Unicode scalar values like 'a', 'α' and '∞' (4 bytes each)
bool either true or false
and the unit type (), whose only possible value is an empty tuple: ()
复合:
arrays like [1, 2, 3]
tuples like (1, true)
自定义:
struct: define a structure
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
structPerson { name: String, age: u8, } // A unit struct structUnit; //useful for generics(template) // A tuple struct structPair(i32, f32); // A struct with two fields structPoint { x: f32, y: f32, }
enum: define an enumeration
1 2 3 4 5 6 7 8 9 10
enumWebEvent { // An `enum` may either be `unit-like`, PageLoad, PageUnload, // like tuple structs, KeyPress(char), Paste(String), // or c-like structures. Click { x: i64, y: i64 }, }
match number { // Match a single value 1 => println!("One!"), // Match several values 2 | 3 | 5 | 7 | 11 => println!("This is a prime"), // Match an inclusive range 13..=19 => println!("A teen"), // Handle the rest of cases _ => println!("Ain't special"), }
match可以做destructing,很有用哦~
Destructuring Tuples
1 2 3 4 5 6 7 8 9 10 11
lettriple = (0, -2, 3);
// Match can be used to destructure a tuple match triple { // Destructure the second and third elements (0, y, z) => println!("First is `0`, `y` is {:?}, and `z` is {:?}", y, z), (1, ..) => println!("First is `1` and the rest doesn't matter"), // `..` can be the used ignore the rest of the tuple _ => println!("It doesn't matter what they are"), // `_` means don't bind the value to a variable }
enumColor { // These 3 are specified solely by their name. Red, Blue, Green, // These likewise tie `u32` tuples to different names: color models. RGB(u32, u32, u32), HSV(u32, u32, u32), }
fnmain() { letcolor = Color::RGB(122, 17, 40);
// An `enum` can be destructured using a `match`. match color { Color::Red => println!("The color is Red!"), Color::Blue => println!("The color is Blue!"), Color::Green => println!("The color is Green!"), Color::RGB(r, g, b) => println!("Red: {}, green: {}, and blue: {}!", r, g, b), Color::HSV(h, s, v) => println!("Hue: {}, saturation: {}, value: {}!", h, s, v), Color::HSL(h, s, l) => println!("Hue: {}, saturation: {}, lightness: {}!", h, s, l), // Don't need another arm because all variants have been examined } }
Destructuring Structures
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
structFoo { x: (u32, u32), y: u32, }
letfoo = Foo { x: (1, 2), y: 3 };
match foo { Foo { x: (1, b), y } => println!("First of x is 1, b = {}, y = {} ", b, y),
// you can destructure structs and rename the variables, // the order is not important Foo { y: 2, x: i } => println!("y is 2, i = {:?}", i),
// and you can also ignore some variables: Foo { y, .. } => println!("y = {}, we don't care about x", y), // this will give an error: pattern does not mention field `x` //Foo { y } => println!("y = {}", y), }
函数
using the fn keyword,参数即跟类型声明一样,如果有返回值,则使用->
1 2 3 4 5 6 7 8 9 10
// Function that returns a boolean value fnis_divisible_by(lhs: u32, rhs: u32) ->bool { // Corner case, early return if rhs == 0 { returnfalse; }
// This is an expression, the `return` keyword is not necessary here lhs % rhs == 0 }
// An integer division that doesn't `panic!` fnchecked_division(dividend: i32, divisor: i32) ->Option<i32> { if divisor == 0 { // Failure is represented as the `None` variant None } else { // Result is wrapped in a `Some` variant Some(dividend / divisor) } }
// This function handles a division that may not succeed fntry_division(dividend: i32, divisor: i32) { // `Option` values can be pattern matched, just like other enums matchchecked_division(dividend, divisor) { None => println!("{} / {} failed!", dividend, divisor), Some(quotient) => { println!("{} / {} = {}", dividend, divisor, quotient) }, } }
fnmain() { lets = String::from("hello"); // s comes into scope
takes_ownership(s); // s's value moves into the function... // ... and so is no longer valid here
letx = 5; // x comes into scope
makes_copy(x); // x would move into the function, // but i32 is Copy, so it’s okay to still // use x afterward
} // Here, x goes out of scope, then s. But because s's value was moved, nothing // special happens.
fntakes_ownership(some_string: String) { // some_string comes into scope println!("{}", some_string); } // Here, some_string goes out of scope and `drop` is called. The backing // memory is freed.
fnmakes_copy(some_integer: i32) { // some_integer comes into scope println!("{}", some_integer); } // Here, some_integer goes out of scope. Nothing special happens.
Borrowing
move操作可发生在传参时,如
1 2 3 4 5 6 7 8 9
fnfunc(s: String) { ///use s do something }// s outof scope, destroy
// Implementation block, all `Point` methods go in here implPoint { // This is a static method // Static methods don't need to be called by an instance // These methods are generally used as constructors fnorigin() -> Point { Point { x: 0.0, y: 0.0 } }
// Another static method, taking two arguments: fnnew(x: f64, y: f64) -> Point { Point { x: x, y: y } } }
implRectangle { // This is an instance method // `&self` is sugar for `self: &Self`, where `Self` is the type of the // caller object. In this case `Self` = `Rectangle` fnarea(&self) ->f64 { // `self` gives access to the struct fields via the dot operator letPoint { x: x1, y: y1 } = self.p1; letPoint { x: x2, y: y2 } = self.p2;
// `abs` is a `f64` method that returns the absolute value of the // caller ((x1 - x2) * (y1 - y2)).abs() }
letrectangle = Rectangle { // Static methods are called using double colons p1: Point::origin(), p2: Point::new(3.0, 4.0), };
// Instance methods are called using the dot operator // Note that the first argument `&self` is implicitly passed, i.e. // `rectangle.perimeter()` === `Rectangle::perimeter(&rectangle)` println!("Rectangle perimeter: {}", rectangle.perimeter()); println!("Rectangle area: {}", rectangle.area());
fnmain() { letarticle = NewsArticle { headline: String::from("Penguins win the Stanley Cup Championship!"), location: String::from("Pittsburgh, PA, USA"), author: String::from("Iceburgh"), content: String::from( "The Pittsburgh Penguins once again are the best \ hockey team in the NHL.", ), };
// define an example struct, make it printable #[derive(Debug)] structFoo;
// an example trait traitBar { fnbaz(&self); }
// implement the trait for Foo implBarforFoo { fnbaz(&self) { println!("{:?}", self) } }
// This is a generic function that takes any T that implements trait Bar. // It must resolve to a specific concrete T at compile time. // The compiler creates a different version of this function // for each concrete type used to call it so &T here is NOT // a trait object (as T will represent a known, sized type // after compilation) fnstatic_dispatch<T>(t: &T) where T: Bar, { t.baz(); // we can do this because t implements Bar }
// This function takes a pointer to a something that implements trait Bar // (it'll know what it is only at runtime). &dyn Bar is a trait object. // There's only one version of this function at runtime, so this // reduces the size of the compiled program if the function // is called with several different types vs using static_dispatch. // However performance is slightly lower, as the &dyn Bar that // dynamic_dispatch receives is a pointer to the object + // a vtable with all the Bar methods that the object implements. // Calling baz() on t means having to look it up in this vtable. fndynamic_dispatch(t: &dyn Bar) { // ----------------^ // this is the trait object! It would also work with Box<dyn Bar> or // Rc<dyn Bar> or Arc<dyn Bar> // t.baz(); // we can do this because t implements Bar }
// Implement the `Animal` trait for `Sheep`. implAnimalforSheep { fnnoise(&self) -> &'staticstr { "baaaaah!" } }
// Implement the `Animal` trait for `Cow`. implAnimalforCow { fnnoise(&self) -> &'staticstr { "moooooo!" } }
// Returns some struct that implements Animal, but we don't know which one at compile time. fnrandom_animal(random_number: f64) ->Box<dyn Animal> { if random_number < 0.5 { Box::new(Sheep {}) } else { Box::new(Cow {}) } }
//box的size是确定的两个usize,指向内存的pointer和对应的length //编译时即知道,你要返回的是一个 pointer和len的组合,是一个长度为两个usize的东西 //如果直接 -> Animal /* fn random_animal(random_number: f64) -> Animal { | ^^^^^^ doesn't have a size known at compile-time */
这部分还有很多设计方面的思想和细节我还没体会理解到,以后再讲~
Closures
Closures are functions that can capture the enclosing environment.
1
|val| val + x
using || instead of () around input variables.
optional body delimination ({}) for a single expression (mandatory otherwise).
the ability to capture the outer environment variables.
fnmain() { // Increment via closures and functions. fnfunction (i: i32) ->i32 { i + 1 }
// Closures are anonymous, here we are binding them to references // Annotation is identical to function annotation but is optional // as are the `{}` wrapping the body. These nameless functions // are assigned to appropriately named variables. letclosure_annotated = |i: i32| ->i32 { i + 1 }; letclosure_inferred = |i | i + 1 ;
leti = 1; // Call the function and closures. println!("function: {}", function(i)); println!("closure_annotated: {}", closure_annotated(i)); println!("closure_inferred: {}", closure_inferred(i));
// A closure taking no arguments which returns an `i32`. // The return type is inferred. letone = || 1; println!("closure returning one: {}", one());