[基础软件理论与实践] 第五节作业实现 採石

採石 2023-02-07 21:24:58

作业信息

  • 课程信息:https://bbs.csdn.net/topics/608593392

作业内容描述:

  1. Complete the type inference ( two substitution functions )
  2. Complete the implementation for let-polymorphism
  3. Think about how to handle recursive functions

作业实现

作業二、三:

先設置類型系統類

type rec typ = TInt | TBool | TVar(ref<tvar>) | TArr(typ, typ) | Gen(array<string>, typ)
and tvar = NoLink(string, int) | LinkTo(typ)

跟Generation相關的類型爲Gen(array<string>, typ),舉例來說,Gen(list{x}, TArr(Var(x), Var(x)),表示forall x. x=>x

下面先上check_expr的主體代碼

1、2的分支,直接返回類型TInt和TBool,無需unify

4的if分支,返回的是fresh出來的t,並分別對(t1, TBool)、(t, t2)、(t, t3)進行unify

5的func分支,fresh出來的tx,返回的是tx->tb,無需unify

6的apply分支,返回的是fresh出來的t,並對(t1, t2->t)進行unify

重點是3分支,遇到generation類型時需實例化類型。以及,8分支,加入遞歸和generation相關邏輯。

先上一些代碼吧,後續,我跟課堂所講的gen算法差異還是比較大的

 注意1、2處,我私以爲,function和let語義,同樣是有層級的。

func x => // level n
  let y = // level n + 1
    x     // level n + 2
  y       // level n + 1

如第一行中的x是第n層fresh出來的t,類型未知。第三行中的x是let解構體的自由變量,同時又是func整體中的受控變量。let-poly中的gen的注意點,在于x變量,可能被函式體內層的其他變量類型確定,成爲更確定的類型,如U(x, TInt), U(x, TInt->y);或x變量,不受內層變量類型影響。下面通過unify函式的邏輯來說明吧。

unify

每次fresh的變量類型,都會帶有當前所在層級的level。故當標誌1那行時,若兩個fresh變量都是未知的,則都用外層的fresh變量替換掉內層的fresh變量。其他情況則在標誌2那行由深層更詳細的類型特徵取代未確定的fresh變量。一般來說,智能識別類型,總是從深層函數推導至外層。

gen

gen(t, level),注意點,在于識別出肯定未被確定的fresh變量,即let所在層級爲n,那麼level大于等於n的fresh變量肯定都是未確定的,而小于n的fresh變量(相對於本層級是自由變量)不一定未確定

inst

類型實例化則比較直接,直接對需要forall的類型參數,依次進行實例化即可

 遞歸

直接略過,我採用了簡單粗暴的實現。

測試輸出

input|- [f] => [a] => [b] => if a { f(b) + 1 } else { f(a) }
nogen|- (Bool -> Int) -> Bool -> Bool -> Int

input|- [x] => { let y = x { y } }
nogen|- Var(T/0)
__gen|- forall: T/0. Var(T/0) -> Var(T/0)

input|- [x] => { let y = { [z] => x } { y } }
__gen|- forall: T/2. Var(T/2) -> Var(T/0)
__gen|- forall: T/0, T/3. Var(T/0) -> Var(T/3) -> Var(T/0)

input|- let id = { [x] => x } { let a = id(42) { let b = id(true) { if b { a } else { 11 } } } }
__gen|- forall: T/1. Var(T/1) -> Var(T/1)
nogen|- Int
nogen|- Bool
nogen|- Int

input|- [f] => { let g = f { g(42) } }
nogen|- Var(T/0)
__gen|- forall: T/2. (Int -> Var(T/2)) -> Var(T/2)

input|- let fact = { [n] => if n == 0 { 1 } else { n × fact(n - 1) } } { fact(5) }
nogen|- Int -> Int
nogen|- Int

 

完整程式碼

mono,constraints

open Belt

let forceGet = Option.getExn
let roundString = str => "(" ++ str ++ ")"

let assoc = (env, x) => env->List.getAssoc(x, (a, b) => a == b)

type rec typ = TInt | TBool | TVar(string) | TArr(typ, typ)

let typ_to_string = typ => {
  let eagerBracket = (x, test) =>
    if test {
      x->roundString
    } else {
      x
    }

  let rec go = (typ, test) =>
    switch typ {
    | TInt => "Int"
    | TBool => "Bool"
    | TVar(x) => "Var" ++ x->roundString
    | TArr(t1, t2) => (go(t1, true) ++ " -> " ++ go(t2, false))->eagerBracket(test)
    }

  go(typ, false)
}

type prim = Add

type rec expr =
  | CstI(int)
  | Var(string)
  | If(expr, expr, expr)
  | Func(string, expr)
  | Apply(expr, expr)
  | Prim(prim, expr, expr)

type constraints = list<(typ, typ)>
type substs = list<(string, typ)>

let infer = expr => {
  let count = ref(0)
  let var_fresher = () => {
    let cur = count.contents
    let var = "T/" ++ cur->Int.toString
    count := cur + 1
    TVar(var)
  }

  let rec check_expr = (context, expr) =>
    switch expr {
    | CstI(_) => (TInt, list{})
    | Var(x) => (context->assoc(x)->forceGet, list{})
    | If(test, so_body, else_body) => {
        let t = var_fresher()
        let (t1, c1) = check_expr(context, test)
        let (t2, c2) = check_expr(context, so_body)
        let (t3, c3) = check_expr(context, else_body)
        (t, List.concatMany([c1, c2, c3, list{(t1, TBool), (t, t2), (t, t3)}]))
      }

    | Func(x, body) => {
        let tx = var_fresher()
        let (tb, cb) = check_expr(list{(x, tx), ...context}, body)
        (TArr(tx, tb), cb)
      }

    | Apply(e1, e2) => {
        let t = var_fresher()
        let (t1, c1) = check_expr(context, e1)
        let (t2, c2) = check_expr(context, e2)
        (t, List.concatMany([c1, c2, list{(t1, TArr(t2, t))}]))
      }

    | Prim(_, e1, e2) => {
        let (t1, c1) = check_expr(context, e1)
        let (t2, c2) = check_expr(context, e2)
        (TInt, List.concatMany([c1, c2, list{(t1, TInt), (t2, TInt)}]))
      }
    }

  let rec type_subst = (typ, subst) => {
    let (x, t) = subst
    switch typ {
    | TVar(y) =>
      if x == y {
        t
      } else {
        typ
      }
    | TArr(t1, t2) => TArr(type_subst(t1, subst), type_subst(t2, subst))
    | _ => typ
    }
  }

  let rec type_substs = (typ, substs) => {
    let rec has_var = typ =>
      switch typ {
      | TVar(_) => true
      | TArr(t1, t2) => has_var(t1) || has_var(t2)
      | _ => false
      }

    let rec go = (typ, substs) =>
      switch substs {
      | list{} => typ
      | list{subst, ...rest} => go(type_subst(typ, subst), rest)
      }

    let t = go(typ, substs)
    if has_var(t) {
      type_substs(t, substs)
    } else {
      t
    }
  }

  let solve = constraints => {
    let rec go = (constraints, s) => {
      let rec occurs = (x, t) =>
        switch t {
        | TVar(y) => x == y
        | TArr(t1, t2) => occurs(x, t1) || occurs(x, t2)
        | _ => false
        }

      switch constraints {
      | list{} => s
      | list{co, ...rest} =>
        switch co {
        | (TInt, TInt) | (TBool, TBool) => go(rest, s)
        | (TArr(t1, t2), TArr(t3, t4)) => go(list{(t1, t3), (t2, t4), ...rest}, s)
        | (TVar(x), t) | (t, TVar(x)) => {
            assert !occurs(x, t)
            let subst = (x, t)
            go(
              rest->List.map(e => {
                let (t1, t2) = e
                (type_subst(t1, subst), type_subst(t2, subst))
              }),
              list{subst, ...s},
            )
          }

        | _ => assert false
        }
      }
    }

    go(constraints, list{})
  }

  let (t, constraints) = check_expr(list{}, expr)
  let substs = solve(constraints)
  type_substs(t, substs)
}

let case = Func(
  "f",
  Func(
    "a",
    Func(
      "b",
      If(Var("a"), Prim(Add, Apply(Var("f"), Var("b")), CstI(1)), Apply(Var("f"), Var("a"))),
    ),
  ),
)

Js.log(case->infer->typ_to_string)

mono,unify

open Belt

let forceGet = Option.getExn
let roundString = str => "(" ++ str ++ ")"
let assoc = (env, x) => env->List.getAssoc(x, (a, b) => a == b)

type rec typ = TInt | TBool | TVar(ref<tvar>) | TArr(typ, typ)
and tvar = NoLink(string) | LinkTo(typ)

let typ_to_string = typ => {
  let eagerBracket = (x, test) =>
    if test {
      x->roundString
    } else {
      x
    }

  let rec go = (typ, test) =>
    switch typ {
    | TInt => "Int"
    | TBool => "Bool"
    | TVar({contents: tvar}) =>
      "Var" ++
      switch tvar {
      | NoLink(x) => roundString(x)
      | LinkTo(_) => assert false
      }
    | TArr(t1, t2) => (go(t1, true) ++ " -> " ++ go(t2, false))->eagerBracket(test)
    }

  go(typ, false)
}

type prim = Add

type rec expr =
  | CstI(int)
  | Var(string)
  | If(expr, expr, expr)
  | Func(string, expr)
  | Apply(expr, expr)
  | Prim(prim, expr, expr)

let infer = expr => {
  let count = ref(0)
  let var_fresher = () => {
    let cur = count.contents
    let var = "T/" ++ cur->Int.toString
    count := cur + 1
    TVar(ref(NoLink(var)))
  }

  let rec repr_type = t =>
    switch t {
    | TVar(tvar) =>
      switch tvar.contents {
      | NoLink(_) => t
      | LinkTo(t) => {
          let t = t->repr_type
          tvar := LinkTo(t)
          t
        }
      }

    | _ => t
    }

  let rec deep_repr_type = t =>
    switch t {
    | TVar(tvar) =>
      switch tvar.contents {
      | NoLink(_) => t
      | LinkTo(t) => {
          let t = t->deep_repr_type
          tvar := LinkTo(t)
          t
        }
      }
    | TArr(t1, t2) => TArr(t1->deep_repr_type, t2->deep_repr_type)

    | _ => t
    }

  let rec unify = (t1, t2) => {
    let rec occurs = (x, t) =>
      switch t {
      | TVar({contents: y}) => x == y
      | TArr(t1, t2) => occurs(x, t1) || occurs(x, t2)
      | _ => false
      }

    let t1 = t1->repr_type
    let t2 = t2->repr_type
    if t1 == t2 {
      ()
    } else {
      switch (t1, t2) {
      | (TInt, TInt) | (TBool, TBool) => ()
      | (TArr(t1, t2), TArr(t3, t4)) => {
          unify(t1, t3)
          unify(t2, t4)
        }

      | (TVar(tvar), t) | (t, TVar(tvar)) => {
          assert !occurs(tvar.contents, t)
          tvar := LinkTo(t)
        }

      | _ => assert false
      }
    }
  }

  let rec check_expr = (context, expr) =>
    switch expr {
    | CstI(_) => TInt
    | Var(x) => context->assoc(x)->forceGet
    | If(test, so_body, else_body) => {
        let t = var_fresher()
        let t1 = check_expr(context, test)
        let t2 = check_expr(context, so_body)
        let t3 = check_expr(context, else_body)
        unify(t1, TBool)
        unify(t, t2)
        unify(t, t3)
        t
      }

    | Func(x, body) => {
        let tx = var_fresher()
        let tb = check_expr(list{(x, tx), ...context}, body)
        TArr(tx, tb)
      }

    | Apply(e1, e2) => {
        let t = var_fresher()
        let t1 = check_expr(context, e1)
        let t2 = check_expr(context, e2)
        unify(t1, TArr(t2, t))
        t
      }

    | Prim(_, e1, e2) => {
        let t1 = check_expr(context, e1)
        let t2 = check_expr(context, e2)
        unify(t1, TInt)
        unify(t2, TInt)
        TInt
      }
    }

  check_expr(list{}, expr)->deep_repr_type
}

let case = Func(
  "f",
  Func(
    "a",
    Func(
      "b",
      If(Var("a"), Prim(Add, Apply(Var("f"), Var("b")), CstI(1)), Apply(Var("f"), Var("a"))),
    ),
  ),
)

Js.log(case->infer->typ_to_string)

poly,unify

open Belt

let forceGet = Option.getExn
let roundString = str => "(" ++ str ++ ")"
let curlyString = str => "{" ++ str ++ "}"
let assoc = (env, x) => env->List.getAssoc(x, (a, b) => a == b)

let curlyBracket = (x, test) =>
  if test {
    (" " ++ x ++ " ")->curlyString
  } else {
    x
  }

type rec typ = TInt | TBool | TVar(ref<tvar>) | TArr(typ, typ) | Gen(array<string>, typ)
and tvar = NoLink(string, int) | LinkTo(typ)

let typ_to_string = typ => {
  let eagerBracket = (x, test) =>
    if test {
      x->roundString
    } else {
      x
    }

  let rec go = (typ, test) =>
    switch typ {
    | TInt => "Int"
    | TBool => "Bool"
    | TVar({contents: tvar}) =>
      "Var" ++
      switch tvar {
      | NoLink(x, _) => x->roundString
      | LinkTo(_) => assert false
      }
    | TArr(t1, t2) => (go(t1, true) ++ " -> " ++ go(t2, false))->eagerBracket(test)
    | Gen(qvars, t) => "forall: " ++ qvars->Array.joinWith(", ", x => x) ++ ". " ++ go(t, false)
    }

  go(typ, false)
}

type prim = Add | Sub | Mul | Eq

type rec expr =
  | CstI(int)
  | CstB(bool)
  | Var(string)
  | If(expr, expr, expr)
  | Func(string, expr)
  | Apply(expr, expr)
  | Prim(prim, expr, expr)
  | Let(string, expr, expr)

let expr_to_string = expr => {
  let rec go = (parent_prior, expr) =>
    switch expr {
    | CstI(n) =>
      if n < 0 {
        n->Int.toString->roundString
      } else {
        n->Int.toString
      }
    | CstB(b) =>
      if b {
        "true"
      } else {
        "false"
      }
    | Var(x) => x
    | If(test, so_body, else_body) =>
      "if " ++
      go(0, test) ++
      " " ++
      go(0, so_body)->curlyBracket(true) ++
      " else " ++
      go(0, else_body)->curlyBracket(true)
    | Func(x, expr) => ("[" ++ x ++ "]" ++ " => " ++ go(1, expr))->curlyBracket(parent_prior > 1)
    | Apply(e1, e2) => go(0, e1) ++ go(0, e2)->roundString
    | Prim(prim, e1, e2) =>
      switch prim {
      | Add => go(0, e1) ++ " + " ++ go(0, e2)
      | Sub => go(0, e1) ++ " - " ++ go(0, e2)
      | Mul => go(0, e1) ++ " × " ++ go(0, e2)
      | Eq => go(0, e1) ++ " == " ++ go(0, e2)
      }
    | Let(x, e1, e2) =>
      ("let " ++ x ++ " = " ++ go(2, e1) ++ " " ++ go(0, e2)->curlyBracket(true))
        ->curlyBracket(parent_prior > 0)
    }

  go(0, expr)
}

let infer = expr => {
  let count = ref(0)
  let var_fresher = level => {
    let cur = count.contents
    let var = "T/" ++ cur->Int.toString
    count := cur + 1
    TVar(ref(NoLink(var, level)))
  }

  let rec repr_type = t =>
    switch t {
    | TVar(tvar) =>
      switch tvar.contents {
      | NoLink(_, _) => t
      | LinkTo(t) => {
          let t = t->repr_type
          tvar := LinkTo(t)
          t
        }
      }

    | _ => t
    }

  let rec deep_repr_type = t =>
    switch t {
    | TVar(tvar) =>
      switch tvar.contents {
      | NoLink(_, _) => t
      | LinkTo(t) => {
          let t = t->deep_repr_type
          tvar := LinkTo(t)
          t
        }
      }
    | TArr(t1, t2) => TArr(t1->deep_repr_type, t2->deep_repr_type)

    | _ => t
    }

  let rec unify = (t1, t2) => {
    let rec occurs = (x, t) =>
      switch t {
      | TVar({contents: y}) => x == y
      | TArr(t1, t2) => occurs(x, t1) || occurs(x, t2)
      | _ => false
      }

    let t1 = repr_type(t1)
    let t2 = repr_type(t2)
    if t1 == t2 {
      ()
    } else {
      switch (t1, t2) {
      | (TInt, TInt) | (TBool, TBool) => ()
      | (TArr(t1, t2), TArr(t3, t4)) => {
          unify(t1, t3)
          unify(t2, t4)
        }

      | (
          TVar({contents: NoLink(_, level1)} as tvar1),
          TVar({contents: NoLink(_, level2)} as tvar2),
        ) =>
        if level1 >= level2 {
          tvar1 := LinkTo(t2)
        } else {
          tvar2 := LinkTo(t1)
        }

      | (TVar(tvar), t) | (t, TVar(tvar)) => {
          assert !occurs(tvar.contents, t)
          tvar := LinkTo(t)
        }

      | _ => assert false
      }
    }
  }

  let inst = (t, level) => {
    let subst = (qvar, new_tvar, t) => {
      let rec go = t =>
        switch t {
        | TInt | TBool => t
        | TVar({contents: tvar}) =>
          switch tvar {
          | NoLink(x, _) =>
            if x == qvar {
              new_tvar
            } else {
              t
            }
          | _ => assert false
          }
        | TArr(t1, t2) => TArr(go(t1), go(t2))

        | Gen(_, _) => assert false
        }

      go(t)
    }

    switch t {
    | Gen(qvars, ti) => {
        let length = qvars->Array.length
        let ti = ref(ti)
        if length > 0 {
          qvars->Array.forEach(qvar => {
            ti := subst(qvar, var_fresher(level), ti.contents)
          })
          ti.contents
        } else {
          assert false
        }
      }

    | _ => t
    }
  }

  let gen = (t, level) => {
    let rec get_qvars = t => {
      switch t {
      | TInt | TBool => []
      | TVar({contents: tvar}) =>
        switch tvar {
        | NoLink(x, level_inner) =>
          if level_inner >= level {
            [x]
          } else {
            []
          }
        | _ => assert false
        }
      | TArr(t1, t2) => Array.concat(t1->get_qvars, t2->get_qvars)

      | Gen(_, _) => assert false
      }
    }

    let t = t->deep_repr_type
    let qvars = t->get_qvars
    if qvars->Array.length > 0 {
      let qvars = HashSet.String.fromArray(qvars)->HashSet.String.toArray
      let t_gen = Gen(qvars, t)
      Js.log("__gen|-\t" ++ typ_to_string(t_gen))
      t_gen
    } else {
      Js.log("nogen|-\t" ++ typ_to_string(t))
      t
    }
  }

  let rec check_expr = (context, expr, level) =>
    switch expr {
    // expr: TInt
    | CstI(_) => TInt
    // expr: TBool
    | CstB(_) => TBool
    | Var(x) => inst(context->assoc(x)->forceGet, level)
    // expr: t = fresh T && U(t1, TBool) U(t, t2) U(t, t3)
    | If(test, so_body, else_body) => {
        let t = var_fresher(level)
        let t1 = check_expr(context, test, level)
        let t2 = check_expr(context, so_body, level)
        let t3 = check_expr(context, else_body, level)
        unify(t1, TBool)
        unify(t, t2)
        unify(t, t3)
        t
      }

    // expr: tx->tb tx = fresh T
    | Func(x, body) => {
        let tx = var_fresher(level)
        let tb = check_expr(list{(x, tx), ...context}, body, level + 1)
        TArr(tx, tb)
      }

    // expr: t = fresh T && U(t1, t2->t)
    | Apply(e1, e2) => {
        let t = var_fresher(level)
        let t1 = check_expr(context, e1, level)
        let t2 = check_expr(context, e2, level)
        unify(t1, TArr(t2, t))
        t
      }

    | Prim(prim, e1, e2) => {
        let t1 = check_expr(context, e1, level)
        let t2 = check_expr(context, e2, level)
        unify(t1, TInt)
        unify(t2, TInt)
        switch prim {
        // expr: TInt && U(t1, TInt) U(t2, TInt)
        | Add | Sub | Mul => TInt
        // expr: TBool && U(t1, TInt) U(t2, TInt)
        | Eq => TBool
        }
      }

    // expr: t2
    | Let(x, e1, e2) => {
        let e1_context = list{(x, var_fresher(level)), ...context}
        let t1 = check_expr(e1_context, e1, level + 1)
        let t_gen = gen(t1, level)
        let e2_context = list{(x, t_gen), ...context}
        let t2 = check_expr(e2_context, e2, level)
        t2
      }
    }

  gen(check_expr(list{}, expr, 0), 0)
}

let cases = [
  Func(
    "f",
    Func(
      "a",
      Func(
        "b",
        If(Var("a"), Prim(Add, Apply(Var("f"), Var("b")), CstI(1)), Apply(Var("f"), Var("a"))),
      ),
    ),
  ),
  Func("x", Let("y", Var("x"), Var("y"))),
  Func("x", Let("y", Func("z", Var("x")), Var("y"))),
  Let(
    "id",
    Func("x", Var("x")),
    Let(
      "a",
      Apply(Var("id"), CstI(42)),
      Let("b", Apply(Var("id"), CstB(true)), If(Var("b"), Var("a"), CstI(11))),
    ),
  ),
  Func("f", Let("g", Var("f"), Apply(Var("g"), CstI(42)))),
  Let(
    "fact",
    Func(
      "n",
      If(
        Prim(Eq, Var("n"), CstI(0)),
        CstI(1),
        Prim(Mul, Var("n"), Apply(Var("fact"), Prim(Sub, Var("n"), CstI(1)))),
      ),
    ),
    Apply(Var("fact"), CstI(5)),
  ),
]

cases->Array.forEach(case => {
  Js.log("input|-\t" ++ expr_to_string(case))
  case->infer->ignore
  Js.log("")
})

然後,我們一起,向rust和rescript編譯器進擊吧,https://www.zhihu.com/people/not3.won

...全文
688 回复 打赏 收藏 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复
代码下载链接: https://pan.quark.cn/s/a4b39357ea24 用户账户控制(UAC)白名单的配置 Windows7环境中 UAC(User Account Control,用户帐户控制)是由微软在Windows Vista版本中推出的一项旨在增强系统安全性的创新技术,该技术强制要求用户在执行可能干扰计算机正常运作的操作或进行更改会波及其他用户设置的变动前,必须提供相应的权限或管理员密码进行验证。通过对这些操作启动前进行授权确认,UAC能够有效阻止恶意软件及间谍软件在未获授权的状态下于计算机内进行安装或实施修改。 自从Vista版本问世以来,微软便开始推行这一全新的安全机制,可视为对系统安全防护的显著提升。尽管UAC确实能够在一定程度上对某些非法程序起到防御作用,但与此同时,这一功能也给众多用户带来了诸多不便。 因此,许多用户开始探寻是否存在类似于白名单的功能,以便将那些值得信赖的程序直接赋予运行权限。事实上,这类功能确实存在,不过微软并未将其作为标准配置提供。 网络上关于此问题的绝大多数建议都是建议禁用UAC,这种说法显然缺乏针对性,因为若用户希望禁用此功能,本就不会提出相关疑问。 通过运用微软官方发布的Microsoft Application Compatibility Toolkit 5.6版本,可以将信任的程序纳入系统白名单范畴。 获取Application Compatibility Toolkit 安装程序成功后会出现三个可执行文件 以管理员身份启动Compatibility Administrator 在Custom DataBases部分创建新的数据库,并添加一个Application Fix(在下方空白处点击右键,选择...
下载代码方式:https://pan.quark.cn/s/a4b39357ea24 DELL服务器的操作系统部署流程包含一系列细致的环节,其适用范围涵盖多种操作系统类型,例如Windows Server与Red Hat Linux等。在启动部署之前,必须确认服务器的光驱设备为DVD驱动器,并且需准备对应的系统安装媒介。下面将详细列出完整的部署步骤: 1. **启动准备**:将随服务器提供的Systems Management Tools and Documentation version 6.0光盘置入服务器光驱,随后设定服务器以光驱作为启动设备。此环节旨在确保服务器在启动阶段能够读取安装光盘内容。 2. **语言设定**:服务器启动后,选定简体中文作为部署语言,并确认接受许可协议条款。 3. **时区选择**:在部署期间,需设定时区为北京、香港、重庆或乌鲁木齐,依据实际地理位置进行适配选择。 4. **系统类型选择**:随后,需选定计划部署的操作系统,支持的版本包括Server 2003 SP2、Server 2003 SP2 64位版本、Windows 2003 SBS SP2、Server 2008、Windows 2008 SBS/EBS x64版本等,以及多种Red Hat和SUSE Linux版本。 5. **RAID设定**:若服务器出厂时已预设RAID配置,则可选择跳过此步骤。若需重新设定RAID,操作时需格外小心,因为这一过程可能引发硬盘数据遗失。 6. **引导分区规划**:设定引导分区的大小,通常C盘建议预留至少20GB的空间,具体容量需根据系统需求进行调整。 7. **网络设定**:网络设定可在系统部署完成后执行,部署期间建议暂时拔除...

231

社区成员

发帖
与我相关
我的任务
社区描述
日程:https://bbs.csdn.net/topics/608593392 主页:https://bobzhang.github.io/courses/ B站: “张宏波的基础软件课程”
rescript开发语言 个人社区 广东省·深圳市
社区管理员
  • raelidea
  • MoonBit月兔
  • 幻灰龙
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧