20200521のLinuxに関する記事は7件です。

arch/arm/kernel/swp_emulate.cの中身も読む

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/arch/arm/kernel/swp_emulate.c

そもそも、swpエミュレーションってなんで必要なの?

簡単にまとめると、

(1) もともと2レジスタ間でデータを交換するSWP命令が存在していた。
(2) マルチコアCPUになったところ、別CPUとの排他制御が必要になった
(3) 上位層にSWP命令使うな、といいたい。だけど、そうも言ってられないので、Kernel側でソフトエミュレーションする仕組みが必要になった。

ですね……。

なお、データ交換するxchg命令は、x86などの別のアーキテクチャでも存在します。

ARM社ドキュメントへのリンク

SWP命令

LDREX命令 / STREX命令

1. 起動時にtrap.cにSWP emurationを登録

swp_emulate.c から traps.c にフック関数の登録依頼

起動時に、 late_initcall(swp_emulation_init);swp_emulation_init()register_undef_hook() ちうコールチェーンになって、swp_handler()がundef_hookで登録される。

arch/arm/kernel/swp_emulate.c"
/*
 * Only emulate SWP/SWPB executed in ARM state/User mode.
 * The kernel must be SWP free and SWP{B} does not exist in Thumb/ThumbEE.
 */
static struct undef_hook swp_hook = {
    .instr_mask = 0x0fb00ff0,
    .instr_val  = 0x01000090,
    .cpsr_mask  = MODE_MASK | PSR_T_BIT | PSR_J_BIT,
    .cpsr_val   = USR_MODE,
    .fn     = swp_handler ★★★★★ココ
};

/*
 * Register handler and create status file in /proc/cpu
 * Invoked as late_initcall, since not needed before init spawned.
 */
static int __init swp_emulation_init(void)
{
    if (cpu_architecture() < CPU_ARCH_ARMv7)
        return 0;

#ifdef CONFIG_PROC_FS
    if (!proc_create_single("cpu/swp_emulation", S_IRUGO, NULL,
            proc_status_show))
        return -ENOMEM;
#endif /* CONFIG_PROC_FS */

    pr_notice("Registering SWP/SWPB emulation handler\n");
    register_undef_hook(&swp_hook); ★★★★★ココ

    return 0;
}

late_initcall(swp_emulation_init); ★★★★★ココ

trap.c は、hook関数を登録する。

arch/arm/kernel/traps.c で登録する。

arch/arm/kernel/traps.c
void register_undef_hook(struct undef_hook *hook)
{
    unsigned long flags;

    raw_spin_lock_irqsave(&undef_lock, flags);
    list_add(&hook->node, &undef_hook);
    raw_spin_unlock_irqrestore(&undef_lock, flags);
}

2. trap発動(させるまで)

ベクタテーブル -> kernelまで

雑に説明すると、ベクターテーブルでundef instructionを見つけると、フック関数に登録しておいたswpのエミュレーション関数が呼ばれる。

arch/arm/kernel/entry-armv.S
vector_rst:
 ARM(   swi SYS_ERROR0  )
 THUMB( svc #0      )
 THUMB( nop         )
    b   vector_und

<略>
/*
 * Undef instr entry dispatcher
 * Enter in UND mode, spsr = SVC/USR CPSR, lr = SVC/USR PC
 */
    vector_stub und, UND_MODE

    .long   __und_usr           @  0 (USR_26 / USR_32)
    .long   __und_invalid           @  1 (FIQ_26 / FIQ_32)
    .long   __und_invalid           @  2 (IRQ_26 / IRQ_32)
    .long   __und_svc           @  3 (SVC_26 / SVC_32) ★★★★★★★★★★★ ココ!!
    .long   __und_invalid           @  4
    .long   __und_invalid           @  5
    .long   __und_invalid           @  6
    .long   __und_invalid           @  7
    .long   __und_invalid           @  8
    .long   __und_invalid           @  9
    .long   __und_invalid           @  a
    .long   __und_invalid           @  b
    .long   __und_invalid           @  c
    .long   __und_invalid           @  d
    .long   __und_invalid           @  e
    .long   __und_invalid           @  f

    .align  5

<略>

    .align  5
__und_svc:
#ifdef CONFIG_KPROBES
    @ If a kprobe is about to simulate a "stmdb sp..." instruction,
    @ it obviously needs free stack space which then will belong to
    @ the saved context.
    svc_entry MAX_STACK_SIZE
#else
    svc_entry
#endif
    @
    @ call emulation code, which returns using r9 if it has emulated
    @ the instruction, or the more conventional lr if we are to treat
    @ this as a real undefined instruction
    @
    @  r0 - instruction
    @
#ifndef CONFIG_THUMB2_KERNEL
    ldr r0, [r4, #-4]
#else
    mov r1, #2
    ldrh    r0, [r4, #-2]           @ Thumb instruction at LR - 2
    cmp r0, #0xe800         @ 32-bit instruction if xx >= 0
    blo __und_svc_fault
    ldrh    r9, [r4]            @ bottom 16 bits
    add r4, r4, #2
    str r4, [sp, #S_PC]
    orr r0, r9, r0, lsl #16
#endif
    badr    r9, __und_svc_finish
    mov r2, r4
    bl  call_fpe

    mov r1, #4              @ PC correction to apply
__und_svc_fault:
    mov r0, sp              @ struct pt_regs *regs
    bl  __und_fault ★★★★★★★★★★★ ココ!!

__und_svc_finish:
    get_thread_info tsk
    ldr r5, [sp, #S_PSR]        @ Get SVC cpsr
    svc_exit r5             @ return from exception
 UNWIND(.fnend      )
ENDPROC(__und_svc)


<略>

__und_fault:
    @ Correct the PC such that it is pointing at the instruction
    @ which caused the fault.  If the faulting instruction was ARM
    @ the PC will be pointing at the next instruction, and have to
    @ subtract 4.  Otherwise, it is Thumb, and the PC will be
    @ pointing at the second half of the Thumb instruction.  We
    @ have to subtract 2.
    ldr r2, [r0, #S_PC]
    sub r2, r2, r1
    str r2, [r0, #S_PC]
    b   do_undefinstr ★★★★★★★★★★★★★★★★★ ココ!!
ENDPROC(__und_fault)

kernel → hook関数

さて、これで無事に do_undefinstrが呼び出される。
ここでは、すでに事前登録されたhook関数を呼び出す関数を呼び出す(めんどい言い方ですが…)

arch/arm/kernel/traps.c
smlinkage void do_undefinstr(struct pt_regs *regs)
{
    unsigned int instr;
    void __user *pc;

    pc = (void __user *)instruction_pointer(regs);

    if (processor_mode(regs) == SVC_MODE) {
<略>
            instr = __mem_to_opcode_arm(*(u32 *) pc);
    } else if (thumb_mode(regs)) {
        if (get_user(instr, (u16 __user *)pc))
            goto die_sig;
        instr = __mem_to_opcode_thumb16(instr);
        if (is_wide_instruction(instr)) {
            unsigned int instr2;
            if (get_user(instr2, (u16 __user *)pc+1))
                goto die_sig;
            instr2 = __mem_to_opcode_thumb16(instr2);
            instr = __opcode_thumb32_compose(instr, instr2);
        }
    } else {
        if (get_user(instr, (u32 __user *)pc))
            goto die_sig;
        instr = __mem_to_opcode_arm(instr);
    }

    if (call_undef_hook(regs, instr) == 0) ★★★★★★★ココ
        return;

<略>
}
NOKPROBE_SYMBOL(do_undefinstr)

call_undef_hook() から、hookに登録したある関数が呼び出される。

arch/arm/kernel/traps.c
static nokprobe_inline
int call_undef_hook(struct pt_regs *regs, unsigned int instr)
{
    struct undef_hook *hook;
    unsigned long flags;
    int (*fn)(struct pt_regs *regs, unsigned int instr) = NULL;

    raw_spin_lock_irqsave(&undef_lock, flags);
    list_for_each_entry(hook, &undef_hook, node)
        if ((instr & hook->instr_mask) == hook->instr_val &&
            (regs->ARM_cpsr & hook->cpsr_mask) == hook->cpsr_val)
            fn = hook->fn;
    raw_spin_unlock_irqrestore(&undef_lock, flags);

    return fn ? fn(regs, instr) : 1;
}

3. trap発動!!

さて、それではフック関数が呼ばれたら、に入ります。

/*
 * swp_handler logs the id of calling process, dissects the instruction, sanity
 * checks the memory location, calls emulate_swpX for the actual operation and
 * deals with fixup/error handling before returning
 */
static int swp_handler(struct pt_regs *regs, unsigned int instr)
{
    unsigned int address, destreg, data, type;
    unsigned int res = 0;

    perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, regs, regs->ARM_pc);

    res = arm_check_condition(instr, regs->ARM_cpsr);
    switch (res) {
    case ARM_OPCODE_CONDTEST_PASS:
        break;
    case ARM_OPCODE_CONDTEST_FAIL:
        /* Condition failed - return to next instruction */
        regs->ARM_pc += 4;
        return 0;
    case ARM_OPCODE_CONDTEST_UNCOND:
        /* If unconditional encoding - not a SWP, undef */
        return -EFAULT;
    default:
        return -EINVAL;
    }

    if (current->pid != previous_pid) {
        pr_debug("\"%s\" (%ld) uses deprecated SWP{B} instruction\n",
             current->comm, (unsigned long)current->pid);
        previous_pid = current->pid;
    }

    address = regs->uregs[EXTRACT_REG_NUM(instr, RN_OFFSET)];
    data    = regs->uregs[EXTRACT_REG_NUM(instr, RT2_OFFSET)];
    destreg = EXTRACT_REG_NUM(instr, RT_OFFSET);

    type = instr & TYPE_SWPB;

    pr_debug("addr in r%d->0x%08x, dest is r%d, source in r%d->0x%08x)\n",
         EXTRACT_REG_NUM(instr, RN_OFFSET), address,
         destreg, EXTRACT_REG_NUM(instr, RT2_OFFSET), data);

    /* Check access in reasonable access range for both SWP and SWPB */
    if (!access_ok((address & ~3), 4)) {
        pr_debug("SWP{B} emulation: access to %p not allowed!\n",
             (void *)address);
        res = -EFAULT;
    } else {
        res = emulate_swpX(address, &data, type);
    }

    if (res == 0) {
        /*
         * On successful emulation, revert the adjustment to the PC
         * made in kernel/traps.c in order to resume execution at the
         * instruction following the SWP{B}.
         */
        regs->ARM_pc += 4;
        regs->uregs[destreg] = data;
    } else if (res == -EFAULT) {
        /*
         * Memory errors do not mean emulation failed.
         * Set up signal info to return SEGV, then return OK
         */
        set_segfault(regs, address);
    }

    return 0;
}

3.1 arm_check_condition

現状の状態で、当該命令を実行するべきかどうかの判断。

  • ARM_OPCODE_CONDTEST_FAIL - 実行する必要なし。
  • ARM_OPCODE_CONDTEST_PASS - 実行しなければならない。
  • ARM_OPCODE_CONDTEST_UNCOND - Never あるいは…
arch/arm/kernel/opcodes.c
/*
 * Returns:
 * ARM_OPCODE_CONDTEST_FAIL   - if condition fails
 * ARM_OPCODE_CONDTEST_PASS   - if condition passes (including AL)
 * ARM_OPCODE_CONDTEST_UNCOND - if NV condition, or separate unconditional
 *                              opcode space from v5 onwards
 *
 * Code that tests whether a conditional instruction would pass its condition
 * check should check that return value == ARM_OPCODE_CONDTEST_PASS.
 *
 * Code that tests if a condition means that the instruction would be executed
 * (regardless of conditional or unconditional) should instead check that the
 * return value != ARM_OPCODE_CONDTEST_FAIL.
 */

3.2 emulate_swpX()

arch/arm/kernel/swp_emulate.c
static int emulate_swpX(unsigned int address, unsigned int *data,
            unsigned int type)
{
    unsigned int res = 0;

    // TYPE_SWPBの場合、アドレスがunalignedだとエラー
    if ((type != TYPE_SWPB) && (address & 0x3)) {
        /* SWP to unaligned address not permitted */
        pr_debug("SWP instruction on unaligned pointer!\n");
        return -EFAULT;
    }

    // 他と調停しながら、__user_swp[b]_asm()を呼び出す。
    // resが-EAGAINだったらやり直し。
    while (1) {
        unsigned long temp;
        unsigned int __ua_flags;

        __ua_flags = uaccess_save_and_enable();
        if (type == TYPE_SWPB)
            __user_swpb_asm(*data, address, res, temp);
        else
            __user_swp_asm(*data, address, res, temp);
        uaccess_restore(__ua_flags);

        if (likely(res != -EAGAIN) || signal_pending(current))
            break;

        cond_resched();
    }

    // カウンタアップ
    if (res == 0) {
        if (type == TYPE_SWPB)
            swpbcounter++;
        else
            swpcounter++;
    }

    return res;
}

3.3 user_swp[b]_arm()

arch/arm/kernel/swp_emulate.c
/*
 * Error-checking SWP macros implemented using ldrex{b}/strex{b}
 */
#define __user_swpX_asm(data, addr, res, temp, B)       \
    __asm__ __volatile__(                   \
    "0: ldrex"B"    %2, [%3]\n"         \
    "1: strex"B"    %0, %1, [%3]\n"         \
    "   cmp     %0, #0\n"           \
    "   moveq       %1, %2\n"           \
    "   movne       %0, %4\n"           \
    "2:\n"                          \
    "   .section     .text.fixup,\"ax\"\n"      \
    "   .align      2\n"                \
    "3: mov     %0, %5\n"           \
    "   b       2b\n"               \
    "   .previous\n"                    \
    "   .section     __ex_table,\"a\"\n"        \
    "   .align      3\n"                \
    "   .long       0b, 3b\n"           \
    "   .long       1b, 3b\n"           \
    "   .previous"                  \
    : "=&r" (res), "+r" (data), "=&r" (temp)        \
    : "r" (addr), "i" (-EAGAIN), "i" (-EFAULT)      \
    : "cc", "memory")

#define __user_swp_asm(data, addr, res, temp) \
    __user_swpX_asm(data, addr, res, temp, "")
#define __user_swpb_asm(data, addr, res, temp) \
    __user_swpX_asm(data, addr, res, temp, "b")

読みやすく書き直してしまうと
ldrexとstrexでデータ交換しているだけになる(後半部分はよくわからないね!)
-EAGAINを介したら、上位層emulate_swpX()で成功するまでリトライされる。

0: ldrex"B"    %temp, [addr]       # [addr]の内容を、tempに読み出す
1: strex"B"    %res, %data, [addr] # dataの内容を、[addr]に書き出す
                                   # resはアップデートされたら0, アップデートできなければ1
   cmp         %res, #0            # res0であるかを判断
   moveq       %data, %temp        # true  => tempの内容をdataに書き出す
   movne       %res, -EAGAIN       # false => res = -EAGAIN
2:
   .section     .text.fixup,"ax"
   .align      2
3: mov         %res, -EFAULT
   b           2b
   .previous
   .section     __ex_table,"a"
   .align      3
   .long       0b, 3b
   .long       1b, 3b
   .previous
    : "=&r" (res), "+r" (data), "=&r" (temp)
    : "r" (addr), "i" (-EAGAIN), "i" (-EFAULT)
    : "cc", "memory"
)

以上です。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Linux基礎3-ファイル操作の基本-

今回は、ファイルの作成・コピー・削除などのLinuxのファイルの基本操作を記事にします。
ファイル操作のコマンドを覚えてしまえば、マウスでのクリックが不便に思えてくるかも知れません。

mkdirコマンド

新しくディレクトリを作成するには、mkdirを使用する

mkdirコマンド
$ mkdir [オプション] <作成するディレクトリ名>

下の図では、ホームディレクトリにworkディレクトリを作成し、lsコマンドで作成したworkディレクトリを確認しています。
lsコマンドのオプションについてはLinuxコマンドリファレンスを参照ください。
今回は-Fと-wを指定しています。
スクリーンショット 2020-05-21 10.22.29.png

すでに同名のファイルが存在する場合にはmkdirは失敗する

下の図では、すでにworkディレクトリが存在している場所に、workディレクトリの作成コマンドを入力した結果です。
mkdirは 「同名のディレクトリが存在します」 とエラーを返します。
スクリーンショット 2020-05-21 10.29.38.png

深いディレクトリを一気に作成したい場合

何階層もある深いディレクトリを作成したい場合があります。
このときmkdirの-pオプションを指定することで、存在しない親ディレクトリも含めて、ディレクトリを作成できます。
下の図では、mkdirをオプションなしで実行した場合と、-pオプションを指定して実行した場合の結果を示しています。-pオプションを指定しない場合、mkdirはエラーを返しますが、-pオプションを指定することで深い階層のディレクトリを作成できます。
スクリーンショット 2020-05-21 10.35.23.png

touchコマンド

Linuxでファイルを作成する方法はたくさんありますが、ここではtouchコマンドを使用します。

touchコマンド
$ touch <新しいファイル名1> <新しいファイル名2> ...

touchコマンドは中身のないファイルを作成します。複数ファイルを同時に作成したい場合には、スペースで区切って並べます
スクリーンショット 2020-05-21 10.51.39.png
本来touchコマンドはファイルのタイムスタンプ(日時)を更新するためのコマンドです。しかし、対象のファイルが存在しない場合には、新しくファイルを作成するという動きをするため、単純に空のファイルを作成するためにも使用できます。
touchコマンドでのファイルの作成は、誤って既存のファイル名を指定しても、内容が上書きされたり、削除されないため安心です。

rmとrmdirコマンド

rmコマンド

rmコマンドはファイルを削除するコマンドです。

rmコマンド
$ rm [オプション] <削除するファイル名1> <削除するファイル名2> ...

複数のファイルを削除したい場合は、touch同様、スペースで区切って並べます。
スクリーンショット 2020-05-21 10.55.35.png

rmでディレクトリの削除

rmでディレクトリを削除するには再帰的にディレクトリツリーを削除する-rオプションを指定します。
このとき、削除対象のディレクトリ内のファイルやディレクトリもまとめて削除しますので注意が必要です。
スクリーンショット 2020-05-21 11.03.14.png

※注意
rmコマンドを実行するとファイルは本当に削除されてしまうため実行前には必ず削除していいものかどうか確認しましょう。WinやMacのようなゴミ箱はありません。

rmdirコマンド

rmと似たコマンドにrmdirというコマンドがあります。これは空のディレクトリを削除するコマンドです。

rmdirコマンド
$ rmdir <ディレクトリ名>

rmコマンドは中にファイルのあるディレクトリを削除しようとしてもエラーとなる点がrmコマンドとの大きな違いです。
スクリーンショット 2020-05-21 11.13.17.png

.hiddenのような隠しファイルがディレクトリ内に残っている場合にもrmdirコマンドでの削除はエラーが返ってきます

rmdirコマンドを使うと中にファイルが存在するディレクトリを誤って削除することを防げます。

catコマンド

catコマンドはファイルの中身を表示するコマンドです。

catコマンド
$ cat [オプション] <ファイル名1> <ファイル名2> ...

作成したばかりのnewfileには中身がないため、catを実行しても何も表示されませんが、中身のあるファイルを指定するとその内容を表示します。
スクリーンショット 2020-05-21 11.28.01.png

複数のファイルを指定した場合、その中身を連結して(連続で)表示します。

行番号を表示する

catコマンドでよく使用されるオプションに -n があります。これは行番号をつけて内容を表示するオプションです。
スクリーンショット 2020-05-21 11.35.01.png

ファイルを指定しない場合

catコマンドでファイルを指定しない場合は、キーボードからの入力を待機するようになります。

catコマンド(引数なし)
$ cat          #引数なしでコマンド実行
Hello          #Helloと入力した
Hello          #Helloと表示される
         #Ctrl+dを入力(キーボード入力終了)
$              #プロンプトが戻る

catだけでなく、多くのLinuxコマンドは入力ファイルを指定しない場合、キーボードからの入力を待機します。この利用方法については後の記事で紹介します。

lessコマンド

catコマンドは単にファイルの中身をそのまま表示するだけでした。そのため表示したい内容が多い場合には、1画面に収まりきらなくなります。このような長いファイルをみたい場合にはlessコマンドを使用します。

lessコマンド
$ less [オプション] <ファイル名>

lessコマンドはファイルの内容を1画面ごとに表示して、画面を上下にスクロールすることができます。

lessコマンドのスクロール操作

コマンド 内容
スペースキー、f、Ctrl+v 1画面下にスクロールする
b、Meta+v 1画面上にスクロールする
j、Ctrl+n、Enter 1行下にスクロールする
k、Ctrl+p 1行上にスクロールする
q lessコマンドを終了する

ファイル内の検索

lessコマンドでは現在開いているファイルから文字列を検索することができます。
ファイルを表示中に「/」を入力すると、一番下の行が検索文字列の入力欄に変わります。
文字列を入力してEnterを叩くことで検索されます。

lessコマンドの検索操作

コマンド 内容
/<文字列> 下方向に向かって検索する
?<文字列> 上方向に向かって検索する
n 次の検索結果に移動する
N 前の検索結果に移動する

下の図は、lessコマンドの検索機能でetcという文字列を検索しています。
スクリーンショット 2020-05-21 11.59.19.png

cpコマンド

ファイルをコピーするためにはcpコマンドを使用します。

cpコマンド
$ cp [オプション] <コピー元> ... <コピー先>

下の図では、newfileをnewfile2としてコピーしています。
スクリーンショット 2020-05-21 12.15.26.png

また、ファイルをディレクトリへコピーすることもできます。これはnewfileをdir1へコピーしています。
スクリーンショット 2020-05-21 12.18.49.png

複数のファイルをディレクトリにコピーする場合は、コピー元のファイルをスペース区切りで並べて、最後の引数にコピー先のディレクトリを指定します。

コピーの際の上書き確認

cpコマンドはコピー先に同名のファイルが存在していたとしても、確認せずに上書きしてしまいます。
ここで-iオプションをつけるとコピー先のファイルが存在する場合に、上書きしても良いかを確認してくれます。[y/n]で回答しましょう。
スクリーンショット 2020-05-21 12.24.38.png

ディレクトリのコピー

cpコマンドではディレクトリをコピーしようとするとエラーになります。
そのため、ディレクトリをコピーする場合は再帰的にコピーを実行する-rオプションを指定します。
このとき、コピー先のディレクトリが存在していない場合には、指定した名前でディレクトリをコピーします。
一方、コピー先のディレクトリが存在している場合には、コピー先にディレクトリを指定したと受け取られて、コピー元をコピー先のディレクトリにコピーします。
スクリーンショット 2020-05-21 12.30.09.png

mvコマンド

ファイルやディレクトリを移動するにはmvコマンドを使用します。

mvコマンド
$ mv [オプション] <移動元> ... <移動先>

<移動元><移動先>にファイルを指定した場合は、ファイル名の変更をしているのと同義になります。
スクリーンショット 2020-05-21 12.37.27.png

cpとは異なり、移動元からファイルがなくなることに注意してください。
また、移動先に同名のファイルが存在する場合には、上書きされてしまう点にも注意してください。-iオプションを指定することで、cp同様、上書き前に確認メッセージを表示できます。

lnコマンド

lnコマンドはリンクを貼るコマンドです。

lnコマンド
$ ln [オプション] <リンク元ファイル名> <リンク名>

リンクとは

Linuxのファイルシステムでは、ファイルに別名をつけることができます。この機能をリンクと呼びます。
リンクには「ハードリンク」「シンボリックリンク」の2種類があります。「ハードリンク」の使用は限定的で、「シンボリックリンク」が頻繁に使用されます。

ハードリンクとは

1つのファイルの実態に複数の名前をつける機能
スクリーンショット 2020-05-21 12.52.05.png

ハードリンクの使用

中身がhelloと表示されるfile1のハードリンクfile2を作成しました。
その後$ cat file2を実行するとfile1と同じ内容が表示されていることがわかります。
意味合いとしては、file1、file2の両方とも、本物の名前と言えます。
スクリーンショット 2020-05-21 12.55.30.png

ハードリンクの削除

ハードリンクをもつファイルの実態は、全てのハードリンクがなくなったときに削除されます。
先ほど作成したハードリンクfile2の元であったfile1を削除しましたが、file2は実体をもっていることが下の図からわかります。
スクリーンショット 2020-05-21 13.01.32.png

シンボリックリンクとは

ハードリンクはディレクトリに対して作成できない、異なるディスク間を跨がることができないという制限があります。一方で、シンボリックリンクはこのような制限を受けないため、シンボリックリンクの方が頻繁に使用されます。

シンボリックリンクとは、リンク先のパス名が書かれた小さな特殊ファイルです。
ハードリンクとは異なり、リンク元のファイルが実体です。
スクリーンショット 2020-05-21 13.08.36.png

シンボリックリンクの使用

シンボリックリンクを使用するにはlnコマンドに-sオプションを指定します。
helloと表示するfile1にシンボリックリンクfile2を作成しました。$ cat file2で表示されているのはfile1の内容(hello)です。

ls -lで詳細情報を表示するとfile2->file1のように、どのファイルへパスを示しているかが確認できます
スクリーンショット 2020-05-21 13.13.10.png

シンボリックリンクの削除

シンボリックリンクはrmコマンドで削除することができます。
シンボリックリンクの実体である元ファイルを削除するとシンボリックリンクは残されますが、リンクが壊れた状態になります。
このときシンボリックリンクを開いても実体がないためエラーを返されます
シェルの設定によっては赤い警告でリンクが壊れたことを教えてくれます。
スクリーンショット 2020-05-21 13.20.04.png

 リンクの利用方法

リンクには次のような使い道があります。参考までに。

長いパス名を省略する
$ ln -s local/work/code/project/source source
$ cd source

参考資料

新しいLinuxの教科書

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Linux基礎4 -ファイル操作の基本-

今回は、ファイルの作成・コピー・削除などのLinuxのファイルの基本操作を記事にします。
ファイル操作のコマンドを覚えてしまえば、マウスでのクリックが不便に思えてくるかも知れません。

mkdirコマンド

新しくディレクトリを作成するには、mkdirを使用する

mkdirコマンド
$ mkdir [オプション] <作成するディレクトリ名>

下の図では、ホームディレクトリにworkディレクトリを作成し、lsコマンドで作成したworkディレクトリを確認しています。
lsコマンドのオプションについてはLinuxコマンドリファレンスを参照ください。
今回は-Fと-wを指定しています。
スクリーンショット 2020-05-21 10.22.29.png

すでに同名のファイルが存在する場合にはmkdirは失敗する

下の図では、すでにworkディレクトリが存在している場所に、workディレクトリの作成コマンドを入力した結果です。
mkdirは 「同名のディレクトリが存在します」 とエラーを返します。
スクリーンショット 2020-05-21 10.29.38.png

深いディレクトリを一気に作成したい場合

何階層もある深いディレクトリを作成したい場合があります。
このときmkdirの-pオプションを指定することで、存在しない親ディレクトリも含めて、ディレクトリを作成できます。
下の図では、mkdirをオプションなしで実行した場合と、-pオプションを指定して実行した場合の結果を示しています。-pオプションを指定しない場合、mkdirはエラーを返しますが、-pオプションを指定することで深い階層のディレクトリを作成できます。
スクリーンショット 2020-05-21 10.35.23.png

touchコマンド

Linuxでファイルを作成する方法はたくさんありますが、ここではtouchコマンドを使用します。

touchコマンド
$ touch <新しいファイル名1> <新しいファイル名2> ...

touchコマンドは中身のないファイルを作成します。複数ファイルを同時に作成したい場合には、スペースで区切って並べます
スクリーンショット 2020-05-21 10.51.39.png
本来touchコマンドはファイルのタイムスタンプ(日時)を更新するためのコマンドです。しかし、対象のファイルが存在しない場合には、新しくファイルを作成するという動きをするため、単純に空のファイルを作成するためにも使用できます。
touchコマンドでのファイルの作成は、誤って既存のファイル名を指定しても、内容が上書きされたり、削除されないため安心です。

rmとrmdirコマンド

rmコマンド

rmコマンドはファイルを削除するコマンドです。

rmコマンド
$ rm [オプション] <削除するファイル名1> <削除するファイル名2> ...

複数のファイルを削除したい場合は、touch同様、スペースで区切って並べます。
スクリーンショット 2020-05-21 10.55.35.png

rmでディレクトリの削除

rmでディレクトリを削除するには再帰的にディレクトリツリーを削除する-rオプションを指定します。
このとき、削除対象のディレクトリ内のファイルやディレクトリもまとめて削除しますので注意が必要です。
スクリーンショット 2020-05-21 11.03.14.png

※注意
rmコマンドを実行するとファイルは本当に削除されてしまうため実行前には必ず削除していいものかどうか確認しましょう。WinやMacのようなゴミ箱はありません。

rmdirコマンド

rmと似たコマンドにrmdirというコマンドがあります。これは空のディレクトリを削除するコマンドです。

rmdirコマンド
$ rmdir <ディレクトリ名>

rmコマンドは中にファイルのあるディレクトリを削除しようとしてもエラーとなる点がrmコマンドとの大きな違いです。
スクリーンショット 2020-05-21 11.13.17.png

.hiddenのような隠しファイルがディレクトリ内に残っている場合にもrmdirコマンドでの削除はエラーが返ってきます

rmdirコマンドを使うと中にファイルが存在するディレクトリを誤って削除することを防げます。

catコマンド

catコマンドはファイルの中身を表示するコマンドです。

catコマンド
$ cat [オプション] <ファイル名1> <ファイル名2> ...

作成したばかりのnewfileには中身がないため、catを実行しても何も表示されませんが、中身のあるファイルを指定するとその内容を表示します。
スクリーンショット 2020-05-21 11.28.01.png

複数のファイルを指定した場合、その中身を連結して(連続で)表示します。

行番号を表示する

catコマンドでよく使用されるオプションに -n があります。これは行番号をつけて内容を表示するオプションです。
スクリーンショット 2020-05-21 11.35.01.png

ファイルを指定しない場合

catコマンドでファイルを指定しない場合は、キーボードからの入力を待機するようになります。

catコマンド(引数なし)
$ cat          #引数なしでコマンド実行
Hello          #Helloと入力した
Hello          #Helloと表示される
         #Ctrl+dを入力(キーボード入力終了)
$              #プロンプトが戻る

catだけでなく、多くのLinuxコマンドは入力ファイルを指定しない場合、キーボードからの入力を待機します。この利用方法については後の記事で紹介します。

lessコマンド

catコマンドは単にファイルの中身をそのまま表示するだけでした。そのため表示したい内容が多い場合には、1画面に収まりきらなくなります。このような長いファイルをみたい場合にはlessコマンドを使用します。

lessコマンド
$ less [オプション] <ファイル名>

lessコマンドはファイルの内容を1画面ごとに表示して、画面を上下にスクロールすることができます。

lessコマンドのスクロール操作

コマンド 内容
スペースキー、f、Ctrl+v 1画面下にスクロールする
b、Meta+v 1画面上にスクロールする
j、Ctrl+n、Enter 1行下にスクロールする
k、Ctrl+p 1行上にスクロールする
q lessコマンドを終了する

ファイル内の検索

lessコマンドでは現在開いているファイルから文字列を検索することができます。
ファイルを表示中に「/」を入力すると、一番下の行が検索文字列の入力欄に変わります。
文字列を入力してEnterを叩くことで検索されます。

lessコマンドの検索操作

コマンド 内容
/<文字列> 下方向に向かって検索する
?<文字列> 上方向に向かって検索する
n 次の検索結果に移動する
N 前の検索結果に移動する

下の図は、lessコマンドの検索機能でetcという文字列を検索しています。
スクリーンショット 2020-05-21 11.59.19.png

cpコマンド

ファイルをコピーするためにはcpコマンドを使用します。

cpコマンド
$ cp [オプション] <コピー元> ... <コピー先>

下の図では、newfileをnewfile2としてコピーしています。
スクリーンショット 2020-05-21 12.15.26.png

また、ファイルをディレクトリへコピーすることもできます。これはnewfileをdir1へコピーしています。
スクリーンショット 2020-05-21 12.18.49.png

複数のファイルをディレクトリにコピーする場合は、コピー元のファイルをスペース区切りで並べて、最後の引数にコピー先のディレクトリを指定します。

コピーの際の上書き確認

cpコマンドはコピー先に同名のファイルが存在していたとしても、確認せずに上書きしてしまいます。
ここで-iオプションをつけるとコピー先のファイルが存在する場合に、上書きしても良いかを確認してくれます。[y/n]で回答しましょう。
スクリーンショット 2020-05-21 12.24.38.png

ディレクトリのコピー

cpコマンドではディレクトリをコピーしようとするとエラーになります。
そのため、ディレクトリをコピーする場合は再帰的にコピーを実行する-rオプションを指定します。
このとき、コピー先のディレクトリが存在していない場合には、指定した名前でディレクトリをコピーします。
一方、コピー先のディレクトリが存在している場合には、コピー先にディレクトリを指定したと受け取られて、コピー元をコピー先のディレクトリにコピーします。
スクリーンショット 2020-05-21 12.30.09.png

mvコマンド

ファイルやディレクトリを移動するにはmvコマンドを使用します。

mvコマンド
$ mv [オプション] <移動元> ... <移動先>

<移動元><移動先>にファイルを指定した場合は、ファイル名の変更をしているのと同義になります。
スクリーンショット 2020-05-21 12.37.27.png

cpとは異なり、移動元からファイルがなくなることに注意してください。
また、移動先に同名のファイルが存在する場合には、上書きされてしまう点にも注意してください。-iオプションを指定することで、cp同様、上書き前に確認メッセージを表示できます。

lnコマンド

lnコマンドはリンクを貼るコマンドです。

lnコマンド
$ ln [オプション] <リンク元ファイル名> <リンク名>

リンクとは

Linuxのファイルシステムでは、ファイルに別名をつけることができます。この機能をリンクと呼びます。
リンクには「ハードリンク」「シンボリックリンク」の2種類があります。「ハードリンク」の使用は限定的で、「シンボリックリンク」が頻繁に使用されます。

ハードリンクとは

1つのファイルの実態に複数の名前をつける機能
スクリーンショット 2020-05-21 12.52.05.png

ハードリンクの使用

中身がhelloと表示されるfile1のハードリンクfile2を作成しました。
その後$ cat file2を実行するとfile1と同じ内容が表示されていることがわかります。
意味合いとしては、file1、file2の両方とも、本物の名前と言えます。
スクリーンショット 2020-05-21 12.55.30.png

ハードリンクの削除

ハードリンクをもつファイルの実態は、全てのハードリンクがなくなったときに削除されます。
先ほど作成したハードリンクfile2の元であったfile1を削除しましたが、file2は実体をもっていることが下の図からわかります。
スクリーンショット 2020-05-21 13.01.32.png

シンボリックリンクとは

ハードリンクはディレクトリに対して作成できない、異なるディスク間を跨がることができないという制限があります。一方で、シンボリックリンクはこのような制限を受けないため、シンボリックリンクの方が頻繁に使用されます。

シンボリックリンクとは、リンク先のパス名が書かれた小さな特殊ファイルです。
ハードリンクとは異なり、リンク元のファイルが実体です。
スクリーンショット 2020-05-21 13.08.36.png

シンボリックリンクの使用

シンボリックリンクを使用するにはlnコマンドに-sオプションを指定します。
helloと表示するfile1にシンボリックリンクfile2を作成しました。$ cat file2で表示されているのはfile1の内容(hello)です。

ls -lで詳細情報を表示するとfile2->file1のように、どのファイルへパスを示しているかが確認できます
スクリーンショット 2020-05-21 13.13.10.png

シンボリックリンクの削除

シンボリックリンクはrmコマンドで削除することができます。
シンボリックリンクの実体である元ファイルを削除するとシンボリックリンクは残されますが、リンクが壊れた状態になります。
このときシンボリックリンクを開いても実体がないためエラーを返されます
シェルの設定によっては赤い警告でリンクが壊れたことを教えてくれます。
スクリーンショット 2020-05-21 13.20.04.png

 リンクの利用方法

リンクには次のような使い道があります。参考までに。

長いパス名を省略する
$ ln -s local/work/code/project/source source
$ cd source

参考資料

新しいLinuxの教科書
Linuxコマンドリファレンス

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

command memo

uptime

起動時間

uptime
12:43  up 97 days,  2:24, 1 user, load averages: 1.93 2.39 2.61

hey

簡易なベンチマークツール

Summary:
  Total:        0.5759 secs
  Slowest:      0.5758 secs
  Fastest:      0.5758 secs
  Average:      0.5758 secs
  Requests/sec: 1.7366


Response time histogram:
  0.576 [1]     |■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
  0.576 [0]     |
  0.576 [0]     |
  0.576 [0]     |
  0.576 [0]     |
  0.576 [0]     |
  0.576 [0]     |
  0.576 [0]     |
  0.576 [0]     |
  0.576 [0]     |
  0.576 [0]     |


Latency distribution:
  0% in 0.0000 secs
  0% in 0.0000 secs
  0% in 0.0000 secs
  0% in 0.0000 secs
  0% in 0.0000 secs
  0% in 0.0000 secs
  0% in 0.0000 secs

Details (average, fastest, slowest):
  DNS+dialup:   0.0516 secs, 0.5758 secs, 0.5758 secs
  DNS-lookup:   0.0009 secs, 0.0009 secs, 0.0009 secs
  req write:    0.0001 secs, 0.0001 secs, 0.0001 secs
  resp wait:    0.4800 secs, 0.4800 secs, 0.4800 secs
  resp read:    0.0441 secs, 0.0441 secs, 0.0441 secs

Status code distribution:
  [200] 1 responses
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Android Smart Phoneをpythonを使ってWeb Serverにする。

Android Smart Phoneをpythonを使ってWeb Serverにする。

Pydroid 3 - IDE for Python 3を使ったけど手を火傷して使用中止!

image.png

image.png

UserLandをGoogle Playよりインストールする。

image.png

image.png

sshでログインする。Rloginを使っています。Port 2022です。

image.png

linux画面が立ち上がります。
image.png

環境整備します。vim editorを使えるようにします。

sudo apt update
sudo apt upgrade -y
sudo apt install -y vim

vim test.c
#include <stdio.h>
int main(){
        printf("hello world\n");
}

hirata@localhost:~$ cc test.c
hirata@localhost:~$ ./a.out
hello world
hirata@localhost:~$

hello worldが出ればOK!

pythonの導入と確認

sudo apt update
sudo apt install python3
sudo apt install python3-pip

hirata@localhost:~$ python3
Python 3.6.9 (default, Apr 18 2020, 01:56:04) 
[GCC 8.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> 

bottoleの導入

sudo pip3 install bottle

テストプログラムの作成

web.py
from bottle import route, run
@route('/')
def root():
    str=""
    for i in range(10):
        str=str+"<h1>Hello %d</h1>"%i
    return str
@route('/hello')
def hello():
    return "<h1>Hello World!</h1>"
run(host='192.168.1.16', port=8080, debug=True)

実行

image.png

Visual Studio 2019で作成されたテンプレートの実行

image.png

.
|-- app.py
|-- routes.py
|-- static
|   |-- content
|   |   |-- bootstrap-grid.css
|   |   |-- bootstrap-grid.css.map
|   |   |-- bootstrap-grid.min.css
|   |   |-- bootstrap-grid.min.css.map
|   |   |-- bootstrap-reboot.css
|   |   |-- bootstrap-reboot.css.map
|   |   |-- bootstrap-reboot.min.css
|   |   |-- bootstrap-reboot.min.css.map
|   |   |-- bootstrap.css
|   |   |-- bootstrap.css.map
|   |   |-- bootstrap.min.css
|   |   |-- bootstrap.min.css.map
|   |   |-- jumbotron.css
|   |   `-- site.css
|   |-- fonts
|   |   |-- glyphicons-halflings-regular.eot
|   |   |-- glyphicons-halflings-regular.svg
|   |   |-- glyphicons-halflings-regular.ttf
|   |   `-- glyphicons-halflings-regular.woff
|   `-- scripts
|       |-- _references.js
|       |-- bootstrap.bundle.js
|       |-- bootstrap.bundle.js.map
|       |-- bootstrap.bundle.min.js
|       |-- bootstrap.bundle.min.js.map
|       |-- bootstrap.js
|       |-- bootstrap.js.map
|       |-- bootstrap.min.js
|       |-- bootstrap.min.js.map
|       |-- jquery-1.10.2.intellisense.js
|       |-- jquery-1.10.2.js
|       |-- jquery-1.10.2.min.js
|       |-- jquery-1.10.2.min.map
|       |-- jquery.validate-vsdoc.js
|       |-- jquery.validate.js
|       |-- jquery.validate.min.js
|       |-- jquery.validate.unobtrusive.js
|       |-- jquery.validate.unobtrusive.min.js
|       |-- modernizr-2.6.2.js
|       |-- respond.js
|       `-- respond.min.js
`-- views
    |-- about.tpl
    |-- contact.tpl
    |-- index.tpl
    `-- layout.tpl
app.py
"""
This script runs the application using a development server.
"""

import bottle
import os
import sys

# routes contains the HTTP handlers for our server and must be imported.
import routes

if '--debug' in sys.argv[1:] or 'SERVER_DEBUG' in os.environ:
    # Debug mode will enable more verbose output in the console window.
    # It must be set at the beginning of the script.
    bottle.debug(True)

def wsgi_app():
    """Returns the application to make available through wfastcgi. This is used
    when the site is published to Microsoft Azure."""
    return bottle.default_app()

if __name__ == '__main__':
    PROJECT_ROOT = os.path.abspath(os.path.dirname(__file__))
    STATIC_ROOT = os.path.join(PROJECT_ROOT, 'static').replace('\\', '/')
    HOST = os.environ.get('SERVER_HOST', 'localhost')
    try:
        PORT = int(os.environ.get('SERVER_PORT', '5555'))
    except ValueError:
        PORT = 5555

    @bottle.route('/static/<filepath:path>')
    def server_static(filepath):
        """Handler for static files, used with the development server.
        When running under a production server such as IIS or Apache,
        the server should be configured to serve the static files."""
        return bottle.static_file(filepath, root=STATIC_ROOT)

    # Starts a local test server.
    HOST,PORT="192.168.1.16",8080
    bottle.run(server='wsgiref', host=HOST, port=PORT)

routes.py
"""
Routes and views for the bottle application.
"""

from bottle import route, view
from datetime import datetime

@route('/')
@route('/home')
@view('index')
def home():
    """Renders the home page."""
    return dict(
        year=datetime.now().year
    )

@route('/contact')
@view('contact')
def contact():
    """Renders the contact page."""
    return dict(
        title='Contact',
        message='Your contact page.',
        year=datetime.now().year
    )

@route('/about')
@view('about')
def about():
    """Renders the about page."""
    return dict(
        title='About',
        message='Your application description page.',
        year=datetime.now().year
    )

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

自分用: ネットワークのメモ

はじめに

ネットワークは前にやったきりで時間も経ってるため、だいぶ忘れてしまいました.
久しぶりにネットワークの復習と追加学習をしました.
その内容をここにメモします.
間違ってたりアドバイスあったら優しく教えてくれると助かります〜

TCP

L3までのおかげでパケットを相手に送信する事ができるようになったが、実際に届いたかどうかはわからない.
なので、相手はパケットが届いたら届いたよ!と、教えたりするルールを設けたのがTCP.(詳しくは省く

パケットを送る時はPORT番号を指定する必要がある.
TCPの場合、相手からのパケットも受け取る必要があるので、依頼元も今回の通信で使うPORT番号を指定する.
送信元PORT番号は[動的・プライベート ポート番号 (49152–65535)]から選ばれる.
つまり、このout用のport番号を超えた65535-49152=16383を超える同時な外部へのTCPでの接続は工夫しないと、基本的にできない.
UDPの場合は、送信元PORTが必要ないので、この動的ポート番号枯渇による起きる制限はない.

ARP

http://www5e.biglobe.ne.jp/aji/3min/26.html

ARPはL3のプロトコルで、ARP Requestをブロードキャストすることにより、ARP Requestに含まれている ARP Replyを頂ける.
ARP ReplyにリクエストされたMACアドレスが含まれた状態で届く.
これを利用することにより、ARP tableに宛先mac addressがない場合でもパケットを届けられるようになる.

ARPのusecaseその4ぐらい

手動でnic設定したstatic ip addressで一度も外部通信していない場合、bridgeやRouterのARP tableにmac addressが記録されていない.
その様な状態の時に、Routerは受け取った宛先 IPのMac AddressをARPを使って調べる.

firewall

firewallでよく80番ポートだけ開放するとかやります.
その場合、80番ポート以外のポートが記載されたパケットを全てロスする設定になっていると、動的ポート番号のパケットまで捨てられてしまいます.
そうした場合、TCPを利用したやりとりができなくなってしまいます.
なので、当たり前ですが、基本的にinとout用でセキュリティで考慮することや設定は変わります.
ちなみにUDPの場合は、response用のポートを動的ポート番号で確保する必要ないので、UDPリクエストしかしないと保証されているようなクライアントがいた場合、全てのportを閉じてもデータを外部に送れます.

NIC

eh0はnic0枚目、eth1はnic1枚目って事
ethN == nicって認識で基本大丈夫
物理レイヤーにパケットを送る場合はethに送信パケットを投げて、ethがそれをethのpeerに対して送る. (nicは基本イーサネットケーブル等を通じて、bridgeやrouter等、対となるnicと繋がっている.その対のことをpeerと呼ぶ.

Router作成の概念

http://redhatlinux.kt.fc2.com/cont/router.htm
このサイトが詳しい.
route -nの見方がわからない場合、このサイトを見るといい.
https://xtech.nikkei.com/it/article/COLUMN/20080520/303086/
http://linux.kororo.jp/cont/intro/dgate.php

コンバージェンスとか一旦置いといた、一番シンプルなRouterはNICから受け取ったパケットを別のNICに飛ばす技術であるip forwardだけで実現が可能.
linuxでip forwardを有効化するには、/etc/sysctl.confnet.ipv4.ip_forward=1を追記し、ネットワークを再起動すると、ip forwardの機能が有効化される.

ifconfig vs ip command

ifconfigはnet-toolsパッケージに含まれているコマンド.
その他にもよく使うroute, netstat, arpなどもnet-toolsパッケージに入っているコマンド.
net-toolsパッケージは現在非推奨になっている.

仮想bridgeの作り方

bridgeは以下のいずれからでも作成できる

  • bridge-utils
  • iproute2
  • netctl
  • systemd-networkd
  • NetworkManager

bridgeにはeth0等の実デバイスとveth等の仮想デバイスを接続することができます

仮想networkの作り方

仮想nicを作りまくって、仮想bridgeに繋げば、仮想プライベートネットワークは作れる.

しかし、このままだとプライベートネットワークがインターネットとやりとりできない.
直接eth0と繋ぐと、今度はeth0が専有されて、プライベートネットワークに所属していない奴らがインターネットに接続できなくなる.
なので、iptablesを使い、ipマスカレードする事によって、できる.
なので、docker等のbridgeのipマスカレードの設定を消すと、完全にネットワークから切り離せる.

ipマスカレード(NAPT

iptablesを使う事により、ipマスカレードを使える.
ipマスカレードを使うと、NAPTの機能はもちろん、port forwardや、securityとかも行える.

port forward

https://qiita.com/Ayaka14/items/449e2236af4b8c2beb81
こんな感じ
iptablesでもできる
特定のportに届いたパケットを特定のip addressのportに転送できる.
L2のproxyとして使える.
また、ネットワークセグメント同士を繋ぐのにも使える.
ネットワークセグメント同士を繋げば、VXLANが構築できる.

VXLAN

https://tech.uzabase.com/entry/2017/08/23/175813
このサイトが詳しい.

冗長化

基本的に対障害の為、単一のマイクロサービスを複数ホストに配置したいので、1マイクロサービスは複数ネットワークセグメント上に展開する.

VXLANの感想

結局はroutingの設定って感じがした.
routingの特定項目の設定とかにport forwardとか色んな特別な名前をつけてる感じ.

参考文献

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

CentOS7のNW設定

はじめに

CentOS7のネットワーク設定についてメモ

ネットワークの設定

NetworkManagerサービスによってネットワーク設定を管理

  • NICを表すデバイス
  • 接続(デバイスに適用する設定)

デバイスに接続(設定)を紐付ける

定義済みのデバイスの確認
CONNECTIONが接続

# nmcli d
DEVICE   TYPE      STATE     CONNECTION 
enp0s25  ethernet  接続済み  enp0s25    
lo       loopback  管理無し  -- 

定義済みの接続の確認

# nmcli c
NAME     UUID                                  TYPE      DEVICE  
enp0s25  173098fd-54de-48b1-95a1-ceaa687089ab  ethernet  enp0s25 

新たな接続の定義

  • 新しく接続したNICに対して新規の接続を紐付ける
  • nmcli -d でデバイスはあるが、接続がない状態

nmcliとnmtuiで接続を作成して、デバイスを紐付ける
nmtuiはGUIで設定できる

VLANデバイスの作成

VLAN77を作成

# nmcli c add type vlan ifname vlan77 con-name vlan-vlan77 dev enp0s25 id 77
接続 'vlan-vlan77' (1092e677-f16b-4a35-8839-19739d20a011) が正常に追加されました。
  1 VLAN=yes
  2 TYPE=Vlan
  3 PHYSDEV=enp0s25
  4 VLAN_ID=77
  5 REORDER_HDR=yes
  6 GVRP=no
  7 MVRP=no
  8 PROXY_METHOD=none
  9 BROWSER_ONLY=no
 10 BOOTPROTO=dhcp
 11 DEFROUTE=yes
 12 IPV4_FAILURE_FATAL=no
 13 IPV6INIT=yes
 14 IPV6_AUTOCONF=yes
 15 IPV6_DEFROUTE=yes
 16 IPV6_FAILURE_FATAL=no
 17 IPV6_ADDR_GEN_MODE=stable-privacy
 18 NAME=vlan-vlan77
 19 UUID=1092e677-f16b-4a35-8839-19739d20a011
 20 DEVICE=vlan77
 21 ONBOOT=yes

上にIPアドレスを設定する

vlanデバイスの稼働確認

 cat /proc/net/vlan/config 
VLAN Dev name    | VLAN ID
Name-Type: VLAN_NAME_TYPE_RAW_PLUS

詳細

# cat /proc/net/vlan/vlan77 
vlan77  VID: 77  REORDER_HDR: 1  dev->priv_flags: 1
         total frames received            0
          total bytes received            0
      Broadcast/Multicast Rcvd            0

      total frames transmitted           13
       total bytes transmitted         1022
Device: enp0s25
INGRESS priority mappings: 0:0  1:0  2:0  3:0  4:0  5:0  6:0 7:0
 EGRESS priority mappings: 
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む