<del id="nnjnj"></del><track id="nnjnj"></track>

<p id="nnjnj"></p>

<address id="nnjnj"></address>

    <pre id="nnjnj"><pre id="nnjnj"></pre></pre>

      <noframes id="nnjnj"><ruby id="nnjnj"><ruby id="nnjnj"></ruby></ruby>

      • 自動秒收錄
      • 軟件:1973
      • 資訊:57811|
      • 收錄網站:279872|

      IT精英團

      Linux環境程序如何運行?

      Linux環境程序如何運行?

      瀏覽次數:
      評論次數:
      編輯: 景同
      信息來源: ITPUB
      更新日期: 2022-09-20 00:44:42
      摘要

      .css-1yuhvjn{margin-top:16px;}.css-3jt6os.FileLinkCard{-webkit-align-items:center;-webkit-box-align

      • 正文開始
      • 相關閱讀
      • 推薦作品
      Card-title.two-line{line-height:20px;display:-webkit-box;text-overflow:ellipsis;overflow:hidden;-webkit-box-orient:vertical;-webkit-line-clamp:2;}.css-1wr1m8 .LinkCard.new .LinkCard-title.loading{margin-bottom:8px;width:80%;}.css-1wr1m8 .LinkCard.new .LinkCard-title.loading.withTitle{margin-bottom:6px;}.css-1wr1m8 .LinkCard.new .LinkCard-title.loadingTitle{margin-bottom:5px;}.css-1wr1m8 .LinkCard.new .LinkCard-excerpt{display:-webkit-box;text-overflow:ellipsis;font-size:13px;line-height:18px;color:#999999;margin-bottom:4px;overflow:hidden;-webkit-box-orient:vertical;-webkit-line-clamp:1;}.css-1wr1m8 .LinkCard.new .LinkCard-excerpt .LinkCard-author{color:#444444;}.css-1wr1m8 .LinkCard.new .LinkCard-desc{display:-webkit-box;font-size:13px;height:18px;line-height:18px;color:#999999;word-break:break-all;text-overflow:ellipsis;overflow:hidden;-webkit-box-orient:vertical;-webkit-line-clamp:1;}.css-1wr1m8 .LinkCard.new .LinkCard-desc .LinkCard-tag,.css-1wr1m8 .LinkCard.new .LinkCard-desc .tag{display:inline-block;font-size:11px;margin-left:8px;padding:0 4px;border-radius:3px;background:rgba(211,211,211,0.3);}.css-1wr1m8 .LinkCard.new .LinkCard-desc.loading{width:40%;}.css-1wr1m8 .LinkCard.new .LinkCard-desc svg{margin-right:2px;}.css-1wr1m8 .LinkCard.new .LinkCard-image{-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;background-color:#EBEBEB;background-size:cover;background-position:center;position:relative;display:block;width:60px;height:60px;margin-left:20px;object-fit:cover;border-radius:inherit;overflow:hidden;}.css-1wr1m8 .LinkCard.new .LinkCard-image.LinkCard-image--default{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;background-color:#EBEBEB;color:#D3D3D3;}.css-1wr1m8 .LinkCard.new .LinkCard-image.LinkCard-image--default svg{color:#999999;}.css-1wr1m8 .LinkCard.new .LinkCard-image img{width:100%;height:100%;object-fit:cover;}.css-1wr1m8 .LinkCard.new .LinkCard-image .LinkCard-image--video{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;position:absolute;top:50%;left:50%;-webkit-transform:translateX(-50%) translateY(-50%);-ms-transform:translateX(-50%) translateY(-50%);transform:translateX(-50%) translateY(-50%);width:24px;height:24px;border-radius:12px;background:rgba(255,255,255,0.9);pointer-events:none;}.css-1wr1m8 .LinkCard.new .LinkCard-image .LinkCard-image--video svg{color:#444444;}.css-1wr1m8 .LinkCard.new .LinkCard-richText .text{color:#444444;}.css-1wr1m8 .LinkCard.new .LinkCard-richText .bold{font-weight:600;}.css-1wr1m8 .LinkCard.new .LinkCard-richText .tag{margin-left:4px;}.css-1wr1m8 .LinkCard.old{position:relative;display:block;margin:1em auto;width:390px;box-sizing:border-box;border-radius:12px;max-width:100%;overflow:hidden;}.css-1wr1m8 .LinkCard.old,.css-1wr1m8 .LinkCard.old:hover{-webkit-text-decoration:none;text-decoration:none;border:none !important;color:inherit !important;}.css-1wr1m8 .LinkCard-ecommerceLoadingCard{position:relative;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:justify;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between;padding:12px;border-radius:inherit;height:80px;box-sizing:border-box;background:rgba(246,246,246,0.88);color:#D3D3D3;}.css-1wr1m8 .LinkCard-ecommerceLoadingCardAvatarWrapper{width:60px;height:60px;background:#EBEBEB;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;border-radius:6px;margin-right:10px;}.css-1wr1m8 .LinkCard-ecommerceLoadingCardNetwork{width:20px;height:20px;}.css-1wr1m8 .LinkCard-ecommerceLoadingCardLoadingbar{height:60px;-webkit-flex:1;-ms-flex:1;flex:1;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;}.css-1wr1m8 .LinkCard-ecommerceLoadingCardLoadingbar span{height:16px;display:inline-block;background:#EBEBEB;}.css-1wr1m8 .LinkCard-ecommerceLoadingCardLoadingbar span:nth-of-type(1){width:60px;margin-bottom:4px;}.css-1wr1m8 .LinkCard-ecommerceLoadingCardLoadingbar span:nth-of-type(2){width:127px;}

      如何啟動程序

      • 雙擊(windows系統下),或者在shell終端上執行./a.out
      • 在shell終端上運行可執行程序的標準流程:
        • 啟動終端仿真器應用程序
        • 輸入可執行文件所在的相對路徑或者絕對路徑
        • 如果該可執行程序需要輸入參數的話,還需要輸入參數

      比如,我們在終端上輸入

      ls --version

      就會出現如下結果。ps 在此處,我們可以人為ls為可執行程序的名稱,--version 是該程序需要的參數。

      ls (GNU coreutils) 8.4Copyright (C) 2010 Free Software Foundation, Inc.License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.This is free software: you are free to change and redistribute it.There is NO WARRANTY, to the extent permitted by law.Written by Richard M. Stallman and David MacKenzie.

      進入bash: /dev/tty

      完整性檢查

      首先,我們從shell的主函數開始,該函數在shell.c文件中。在主函數執行之前,主要做了以下準備工作:

      • 檢查并嘗試打開/dev/tty
      • 檢查shell是否在調試模式下運行
      • 分析命令行參數
      • 讀取shell環境
      • 加載.bashrc、.profile和其他配置文件等。

      構建運行環境

      在做完上述完整性檢查之后,最終會執行reader_loop函數,該函數,定義在eval.c中,主要作用是讀取給定的程序名稱和參數。然后從execute_cmd.c調用execute_command函數,依次調用以下函數鏈, 不同的檢查,例如我們是否需要啟動subshell,是否內置bash函數等等。

      reader_loop-> execute_command--> execute_command_internal----> execute_simple_command------> execute_disk_command--------> shell_execve

      眾所周知,Linux的實現語言是c,shell也是其一個應用,也有自己的main函數。 進入main函數后,在基本的初始化操作之后,最終進入reader_loop函數。 reader_loop會調用execute_command來等待用戶輸入命令行參數,在用戶輸入參數之后,將調用execute_command_internal函數。 execute_command_internal函數是shell源碼中執行命令的實際操作函數。他需要對作為操作參數傳入的具體命令結構的value成員進行分析,并針對不同的value類型,再調用具體類型的命令執行函數進行具體命令的解釋執行工作。

      具體來說:如果value是simple,則直接調用execute_simple_command函數進行執行,execute_simple_command再根據命令是內部命令或磁盤外部命令分別調用execute_builtin和execute_disk_command來執行,其中,execute_disk_command在執行外部命令的時候調用make_child函數fork子進程執行外部命令。

      如果value是其他類型,則調用對應類型的函數進行分支控制。舉例來說,如果是value是for_commmand,即這是一個for循環控制結構命令,則調用execute_for_command函數。在該函數中,將枚舉每一個操作域中的元素,對其再次調用execute_command函數進行分析。即execute_for_command這一類函數實現的是一個命令的展開以及流程控制以及遞歸調用execute_command的功能。 在上述整個調用流程串的最后一步是shell_execve。 該函數最終會調用系統函數execve,其聲明如下:

      int execve(const char *filename, char *const argv [], char *const envp[]);

      在該函數中,有三個參數,分別是:

      • filename可執行文件的名稱
      • 可執行文件所需的參數
      • 可執行文件所在的環境變量 在該函數中,最終就是運行可執行程序,這一步操作,是在kernel中操作的。

      進入內核: execve系統調用

      execve系統調用實現

      該函數定義在fs/exec.c中,其聲明如下:

      SYSCALL_DEFINE3(execve,const char __user *, filename,const char __user *const __user *, argv,const char __user *const __user *, envp){      return do_execve(getname(filename), argv, envp);}

      execve的實現在這里非常簡單,只調用了do_execve函數,其參數為execve的參數。 而do_execve函數的定義如下:

      int do_execve(struct filename *filename,const char __user *const __user *__argv,const char __user *const __user *__envp){    struct user_arg_ptr argv = { .ptr.native = __argv };    struct user_arg_ptr envp = { .ptr.native = __envp };    return do_execveat_common(AT_FDCWD, filename, argv, envp, 0);}

      通過上述代碼,我們可以看到,在do_execve中,最終調用了do_execveat_common,其除了使用do_execve中的參數之外,還有額外的兩個參數。 下面是do_execveat_common的具體代碼(此處我們去掉了一些不必要放入判斷代碼)

      static int do_execveat_common(int fd, struct filename *filename,         struct user_arg_ptr argv,         struct user_arg_ptr envp,         int flags){ struct linux_binprm *bprm; int retval; if (IS_ERR(filename))  return PTR_ERR(filename); ... current->flags &= ~PF_NPROC_EXCEEDED; bprm = alloc_bprm(fd, filename); if (IS_ERR(bprm)) {  retval = PTR_ERR(bprm);  goto out_ret; } retval = count(argv, MAX_ARG_STRINGS); bprm->argc = retval; retval = count(envp, MAX_ARG_STRINGS); bprm->envc = retval; retval = bprm_stack_limits(bprm);  retval = copy_string_kernel(bprm->filename, bprm); bprm->exec = bprm->p; retval = copy_strings(bprm->envc, envp, bprm);  retval = copy_strings(bprm->argc, argv, bprm);  retval = bprm_execve(bprm, fd, filename, flags); putname(filename); return retval;}

      安全性檢查

      第一個參數AT_FDCWD是當前目錄的文件描述符,第五個參數是標志。 我們稍后會看到。 do_execveat_common函數檢查文件名指針并返回它是否為NULL。 在此之后,它檢查當前進程的標志,表明未超出正在運行的進程的限制:

      if (IS_ERR(filename))    return PTR_ERR(filename);if ((current->flags & PF_NPROC_EXCEEDED) &&atomic_read(&current_user()->processes) > rlimit(RLIMIT_NPROC)) {    retval = -EAGAIN;    goto out_ret;}current->flags &= ~PF_NPROC_EXCEEDED;

      如果這兩項檢查成功,我們將在當前進程的標志中取消設置PF_NPROC_EXCEEDED標志,以防止執行程序失敗。 在下一步中,我們調用在kernel/fork.c中定義的unshare_files函數,并取消共享當前任務的文件,并檢查此函數的結果:

      retval = unshare_files(&displaced);if (retval)    goto out_ret;

      調用此函數的目的旨在消除執行二進制文件的文件描述符的潛在泄漏。 在下一步中,我們開始準備由struct linux_binprm結構(在include/linux/binfmts.h頭文件中定義)表示的bprm。

      二進制參數準備

      struct linux_binprm

      linux_binprm結構用于保存加載二進制文件時使用的參數。 例如,它包含vm_area_struct,表示將在給定地址空間中連續間隔內的單個內存區域,將在該空間中加載應用程序。mm字段,它是二進制文件的內存描述符,指向內存頂部的指針以及許多其他不同的字段。

      分配內存

      在do_execveat_common函數中,執行alloc_bprm函數,最終會調用如下:

      bprm = kzalloc(sizeof(*bprm), GFP_KERNEL);if (!bprm)    goto out_files;

      準備工作

      retval = prepare_bprm_creds(bprm);if (retval)    goto out_free;check_unsafe_exec(bprm);current->in_execve = 1;

      初始化linux_binprm中的cred結構變量,該結構變量中包含任務的實際uid,任務的實際guid,虛擬文件系統操作的uid和guid等。 然后,對check_unsafe_exec函數的調用將當前進程設置為in_execve狀態。

      計算命令行參數和環境變量

      bprm->argc = count(argv, MAX_ARG_STRINGS);if ((retval = bprm->argc) < 0)    goto out;bprm->envc = count(envp, MAX_ARG_STRINGS);if ((retval = bprm->envc) < 0)    goto out;

      在上述代碼中,MAX_ARG_STRINGS是頭文件中定義的上限宏,它表示傳遞給execve系統調用的最大字符串數。 MAX_ARG_STRINGS的值:

      `#define MAX_ARG_STRINGS 0x7FFFFFFF`

      設置

      完成所有這些操作后,我們調用do_open_execat函數,該函數

      • 搜索并打開磁盤上的可執行文件并檢查,
      • 從noexec掛載點繞過標志0加載二進制文件(我們需要避免從不包含proc或sysfs等可執行二進制文件的文件系統中執行二進制文件),
      • 初始化文件結構并返回此結構上的指針。 接下來,我們可以在此之后看到對sched_exec的調用。 sched_exec函數用于確定可以執行新程序的最小負載處理器,并將當前進程遷移到該處理器。
      file = do_open_execat(fd, filename, flags);retval = PTR_ERR(file);if (IS_ERR(file))    goto out_unmark;sched_exec();

      之后,我們需要檢查給出可執行二進制文件的文件描述符。 我們嘗試檢查二進制文件的名稱是否從/符號開始,或者給定的可執行二進制文件的路徑是否相對于調用進程的當前工作目錄進行了解釋,或者文件描述符為AT_FDCWD。 如果這些檢查之一成功,我們將設置二進制參數文件名:

      bprm->file = file;if (fd == AT_FDCWD || filename->name[0] == '/') {    bprm->filename = filename->name;}

      否則,如果文件名稱為空,則將文件名設置為/dev/fd/%d (即/dev/fd/文件描述符),否則將文件名重新設置為/dev/fd/%d/文件名(其中,fd指向可執行文件的文件描述符)

      } else {        if (filename->name[0] == '\0')        pathbuf = kasprintf(GFP_TEMPORARY, "/dev/fd/%d", fd);    else        pathbuf = kasprintf(GFP_TEMPORARY, "/dev/fd/%d/%s",    fd, filename->name);            if (!pathbuf) {        retval = -ENOMEM;        goto out_unmark;    }        bprm->filename = pathbuf;}bprm->interp = bprm->filename;

      需要注意的是,我們不僅設置了bprm-> filename,還設置了bprm-> interp,它將包含程序解釋器的名稱。 現在,我們只是在此處寫相同的名稱,但是稍后將使用程序解釋器的真實名稱對其進行更新,其具體取決于程序的二進制格式。

      準備內存相關信息

      retval = bprm_mm_init(bprm);if (retval)     goto out_unmark;

      其中,bprm_mm_init的定義如下:

      static int bprm_mm_init(struct linux_binprm *bprm){ int err; struct mm_struct *mm = NULL; bprm->mm = mm = mm_alloc(); err = -ENOMEM; if (!mm)  goto err; /* Save current stack limit for all calculations made during exec. */ task_lock(current->group_leader); bprm->rlim_stack = current->signal->rlim[RLIMIT_STACK]; task_unlock(current->group_leader); err = __bprm_mm_init(bprm); if (err)  goto err; return 0;err: if (mm) {  bprm->mm = NULL;  mmdrop(mm); } return err;}

      在函數bprm_mm_init中,其功能主要是初始化mm_struct 和 vm_area_struct結構。

      讀取二進制(ELF)文件

      調用prepare_binprm函數將inode的uid填充到linux_binprm結構中,并從二進制可執行文件中讀取128個字節。 我們只從可執行文件中讀取前128個,因為我們需要檢查可執行文件的類型。 我們將在后續步驟中閱讀可執行文件的其余部分。

      retval = prepare_binprm(bprm);if (retval < 0)    goto out;

      準備好linux_bprm結構后,我們通過調用copy_strings_kernel函數將可執行二進制文件的文件名,命令行參數和環境變量從內核復制到linux_bprm:

      retval = copy_strings_kernel(1, &bprm->filename, bprm);if (retval < 0)    goto out;retval = copy_strings(bprm->envc, envp, bprm);if (retval < 0)    goto out;retval = copy_strings(bprm->argc, argv, bprm);if (retval < 0)    goto out;

      并將指針設置為我們在bprm_mm_init函數中設置的新程序堆棧的頂部bprm-> exec = bprm-> p; 堆棧的頂部將包含程序文件名,我們將該文件名存儲到linux_bprm結構的exec字段中。

      處理參數結構

      通過調用exec_binprm函數來存儲當前當前任務所在進程的pid

      retval = exec_binprm(bprm);if (retval < 0)    goto out;

      在exec_binprm函數中,也會調用search_binary_handler。 當前,Linux內核支持以下二進制格式:

      • binfmt_script: 支持從#!開始的解釋腳本。 線;
      • binfmt_misc: 根據Linux內核的運行時配置,支持不同的二進制格式;
      • binfmt_elf: 支持elf格式;
      • binfmt_aout: 支持a.out格式;
      • binfmt_flat: 支持平面格式;
      • binfmt_elf_fdpic: 支持elf FDPIC二進制文件;
      • binfmt_em86: 支持在Alpha機器上運行的Intel elf二進制文件。 因此,search_binary_handler嘗試調用load_binary函數并將linux_binprm傳遞給該函數。 如果二進制處理程序支持給定的可執行文件格式,它將開始準備可執行二進制文件的前期工作。該函數定義如下:
      int search_binary_handler(struct linux_binprm *bprm){    ...    ...    ...    list_for_each_entry(fmt, &formats, lh) {    retval = fmt->load_binary(bprm);        if (retval < 0 && !bprm->mm) {        force_sigsegv(SIGSEGV, current);        return retval;    }}return retval;

      在load_binary中檢查linux_bprm緩沖區中的魔數(每個elf二進制文件的頭中都包含魔數,我們從可執行二進制文件中讀取了前128個字節),如果不是elf二進制,則退出。

      運行

      完整性檢測

      如果給定的可執行文件為elf格式,則load_elf_binary繼續并檢查可執行文件的體系結構和類型,并在體系結構錯誤且可執行文件不可執行,不可共享時退出:

      if (loc->elf_ex.e_type != ET_EXEC && loc->elf_ex.e_type != ET_DYN)    goto out;if (!elf_check_arch(&loc->elf_ex))    goto out;

      設置地址空間和依賴

      嘗試加載描述段的程序頭表。 從磁盤上讀取與我們的可執行二進制文件鏈接的程序解釋器和庫,并將其加載到內存中。

      elf_phdata = load_elf_phdrs(&loc->elf_ex, bprm->file);if (!elf_phdata)    goto out;

      程序解釋器指定在可執行文件的.interp部分(在大多數情況下,對于x86_64,鏈接器為– /lib64/ld-linux-x86-64.so.2)。 它設置堆棧并將elf二進制文件映射到內存中的正確位置,映射了bss和brk部分,并做了許多其他不同的事情來準備要執行的可執行文件。 在執行load_elf_binary的最后,我們調用start_thread函數并將三個參數傳遞給該函數:

      start_thread(regs, elf_entry, bprm->p);    retval = 0;out:    kfree(loc);out_ret:    return retval;

      這些參數是:

      • 新任務的寄存器集
      • 新任務入口點的地址
      • 新任務的堆棧頂部地址 從函數名稱可以理解,它啟動了一個新線程,但事實并非如此。 start_thread函數只是準備新任務的寄存器以準備運行。下面是定義:
      voidstart_thread(struct pt_regs *regs, unsigned long new_ip, unsigned long new_sp){    start_thread_common(regs, new_ip, new_sp,    __USER_CS, __USER_DS, 0);}

      通過上面代碼,我們能夠看到,在start_thread函數中,最終還是調用了start_thread_common函數。

      開始執行

      static voidstart_thread_common(struct pt_regs *regs, unsigned long new_ip,unsigned long new_sp,unsigned int _cs, unsigned int _ss, unsigned int _ds){    loadsegment(fs, 0);    loadsegment(es, _ds);    loadsegment(ds, _ds);    load_gs_index(0);    regs->ip = new_ip;    regs->sp = new_sp;    regs->cs = _cs;    regs->ss = _ss;    regs->flags = X86_EFLAGS_IF;    force_iret();}

      start_thread_common函數將fs段寄存器填充為零,并將es&ds填充數據段寄存器的值。之后,我們將新值設置為指令指針,cs段等。在start_thread_common函數的末尾,我們可以看到force_iret宏,該宏通過iret指令強制返回系統調用。

      然后,創建了在用戶空間中運行的新線程,隨后可以從exec_binprm返回,再次處于do_execveat_common中。 exec_binprm完成執行后,釋放之前分配的結構的內存,然后返回。

      從execve系統調用處理程序返回后,將開始執行程序。之所以可以這樣做,是因為之前配置了所有與上下文相關的信息。

      如我們所見,execve系統調用不會將控制權返回給進程,但是調用者進程的代碼,數據和其他段只是被程序段所覆蓋。 應用程序的退出將通過退出系統調用實現。

      至此,整個程序從開始運行到退出,整個流程完。

      標簽:函數 參數 程序
      轉:Java老了 科特林會取而代之嗎?
      ? 上一篇 2022-09-20
      記錄在線超時的分析和故障排除過程
      下一篇 ? 2022-09-20
      • 如何在Ubuntu中保留文件系統并備份當前開發板鏡像
        0閱讀 0條評論 個贊
        在Ubuntu保留文件系統或者說備份當前開發板鏡像的需求在不斷增加。比如Ubuntu文件系統需要安裝庫文件的話直接使用apt-get工具就可以下載,但由于需要下載的核心板較多,比較費時間,這時需要將安……
      • 國產核心板全志T507助力消防系統升級
        0閱讀 0條評論 個贊
        9月16日下午,位于湖南長沙市區內的中國電信大樓發生火災,建筑高度218米,現場濃煙滾滾,數十層樓體燃燒劇烈。消防救援人員趕到現場后很快將火勢控制住,目前大樓火勢已被撲滅,所幸未發現人員傷亡。湖南電信……
      • 教大家如何處理Spring Boot易流中的用戶和群體!
        0閱讀 0條評論 個贊
        1.準備工作2.用戶操作2.1添加用戶2.2修改用戶2.3刪除用戶2.4查詢用戶3.組操作3.1添加組3.2修改組3.3刪除組3.4查詢組4.查看表詳情雖然說我們在實際開發中,……
      • 從PG15開始WAL壓縮優化
        0閱讀 0條評論 個贊
        PG15傳聞中的超級令人激動的功能大多數跳票了,年初我也寫過一個關于PG15新功能跳票的文章。PG15BETA已經發出幾個月了,似乎PG15里令人激動人心的功能不多,不過從長長的新功能列表里,……
      • 深入了解美團葉子發射器開源方案
        0閱讀 0條評論 個贊
        大家好,我是樹哥。之前我們有聊過「如何設計一個分布式ID發號器」,其中有講過4種解決方案,分別是:UUID類雪花算法數據庫自增主鍵Redis原子自增美團以第2、3種解決方案為基礎,開發出……
      發表評論 共有條評論
      用戶名: 密碼:
      驗證碼: 匿名發表
      • 在頭腦中扎根泛型的思想3354深刻理解泛型
        0閱讀 0條評論 個贊
        1.前言往往一些剛接觸C#編程的初學者,對于泛型的認識就是直接跳到對泛型集合的使用上,雖然微軟為我們提供了很多內置的泛型類型,但是如果我們只是片面的了解調用方式,這會導致我們對泛型盲目的使用。至于為什……
      • SQL Server聯接方式
        0閱讀 0條評論 個贊
        0.參考文獻MicrosoftSQLServer企業級平臺管理實踐看懂SqlServer查詢計劃1.測試數據準備參考:SqlServer中的表訪問方式TableScan,IndexScan……
      • 開發者如何在應用后臺直接控制用戶的運動狀態?
        18閱讀 0條評論 個贊
        酷暑終于過去,很多人伴著涼爽的秋風開啟了新一輪的健身計劃。當用戶進行戶外運動或使用跑步機、橢圓機等器械時,他們會希望在運動健康類App里點擊即可開啟運動并記錄運動數據。而對于開發者自己開發的應用來說,……
      • Linux環境程序如何運行?
        0閱讀 0條評論 個贊
        .css-1yuhvjn{margin-top:16px;}.css-3jt6os.FileLinkCard{-webkit-align-items:center;-webkit-box-align……
      • 關于Redis在windows上運行的問題和fork函數
        0閱讀 0條評論 個贊
        Redis在將數據庫進行持久化操作時,需要fork一個進程,但是windows并不支持fork,導致在持久化操作期間,Redis必須阻塞所有的客戶端直至持久化操作完成。微軟的一些工程師花費時間在解決在……
      • Java內存區(運行時數據區)簡介
        0閱讀 0條評論 個贊
        Java虛擬機在執行Java程序的過程中會把它管理的內存劃分成若干個不同的數據區域。JDK1.8和之前的版本略有不同。下圖是JDK1.8對JVM做的改動,把方法區的具體實現----元空……
      • 深入了解美團葉子發射器開源方案
        0閱讀 0條評論 個贊
        大家好,我是樹哥。之前我們有聊過「如何設計一個分布式ID發號器」,其中有講過4種解決方案,分別是:UUID類雪花算法數據庫自增主鍵Redis原子自增美團以第2、3種解決方案為基礎,開發出……
      • 舉例說明庫伯內特公司的豆莢核心資源
        3閱讀 0條評論 個贊
        目錄一、Pod定義二、Pod入門yaml描述文件三、共享NetworkNamespace四、共享PID五、容器生命周期六、初始化容器6.1、簡介6.2、與普通容器的區別6.3、實驗七、Pod探針7.1……
      • 二戰MySQL數據庫【升華】
        0閱讀 0條評論 個贊
        MYSQL入門系列——第二篇1.篩選條件:(1)比較運算符:(2)邏輯運算符:(3)其他操作:1.排序:2.限制:拓展:3.去重:4.模糊查詢:(like'%')5.范圍查詢:2.聚合與分組(重點……
      • Sql Server系列:分區表操作
        0閱讀 0條評論 個贊
        1.分區表簡介分區表在邏輯上是一個表,而物理上是多個表。從用戶角度來看,分區表和普通表是一樣的。使用分區表的主要目的是為改善大型表以及具有多個訪問模式的表的可伸縮性和可管理性。分區表是把數據……
      • 大促銷活動如何抵御高流量DDoS攻擊?
        0閱讀 0條評論 個贊
        大促活動如何抵御大流量DDoS攻擊?每一次活動大促帶來的迅猛流量,對技術人而言都是一次嚴峻考驗。如果在活動期間遭受黑產惡意DDoS攻擊,無疑是雪上加霜。電商的特性是業務常態下通常不會遭受大流量DD……
      • JavaScript設計模式和代碼實現——單例模式
        0閱讀 0條評論 個贊
        單例模式1定義#保證一個類僅有一個實例,并提供一個訪問它的全局訪問點。2應用時機#當一個類的實例被頻繁使用,如果重復創建這個實例,會無端消耗資源。比如dialog彈窗會被全局重復使用業務功能本……
      • 數據庫發展史1-傳統數據庫
        0閱讀 0條評論 個贊
        1946年,美國賓夕法尼亞大學誕生了人類第一臺電子計算機--ENIAC(ElectronicNumericalIntegratorAndComputer,即電子數字積分計算機),這個占地170……
      • 新零售SaaS架構:商品系統架構設計
        0閱讀 0條評論 個贊
        SaaS產品就像一座冰山,冰山以上的部分是功能、數據(可見部分)、用戶界面,冰山以下是系統架構、完整的數據模型、開放體系、非功能性需求(擴展性、可維護性、性能、安全等)。短期內想要快速上線產品,可能只……
      • 圖解架構| SaaS、PaaS、IaaS
        0閱讀 0條評論 個贊
        這是悟空的第164篇原創文章官網:www.passjava.cn你好,我是悟空哥。上次聊到了架構圖如何畫,其中涉及到了云服務的架構圖,里面提到了很重要的三個概念PaaS、IaaS、SaaS,很有必要……
      • SQL Server備份和還原攻略
        0閱讀 0條評論 個贊
        一、知識點完全備份:備份全部選中的文件夾,并不依賴文件的存檔屬性來確定備份那些文件。(在備份過程中,任何現有的標記都被清除,每個文件都被標記為已備份,換言之,清除存檔屬性)。完全備份也叫完整備份。差異……
      • 面試官:為什么系統不推薦雙寫?
        0閱讀 0條評論 個贊
        某日,阿雄跑去面試!于是有如下情形面試官:"阿雄是吧,做做自我介紹!"阿雄:"我叫阿雄,來自某a國際電商公司!"面試官:"我看你項目里用了elasticsearch,你是怎么同步數據的呢?"阿……
      • 【云原生】-碼頭工人容器遷移神諭到關系型數據庫
        0閱讀 0條評論 個贊
        文章目錄前言??1.創建專用網絡??2.Oracle12C部署?2.1鏡像下載?2.2容器創建?2.3創建業務用戶?2.4監聽啟動??3.MySQL8部署?3.1容器……
      • 適時變革 共創未來| 2022數字技能職業教育生態研討會圓滿落幕
        0閱讀 0條評論 個贊
        2022年8月25日,由恒利聯創主辦的“適時而變,聯創未來”2022數字技能職業教育生態研討會在線上舉行。本屆大會圍繞“數字技能職業教育和數字化人才培養”的話題,邀請了Oracle技術人才發展部總經理……
      • 碼頭工人日常工作的常用命令
        0閱讀 0條評論 個贊
        容器生命周期管理Docker創建新容器并運行[run]語法:dockerrun[OPTIONS]IMAGE[COMMAND][ARG...]OPTIONS說明:-astdin:指定標準輸入……
      最近發布資訊
      更多
      警花高潮嗷嗷叫
      <del id="nnjnj"></del><track id="nnjnj"></track>

      <p id="nnjnj"></p>

      <address id="nnjnj"></address>

        <pre id="nnjnj"><pre id="nnjnj"></pre></pre>

          <noframes id="nnjnj"><ruby id="nnjnj"><ruby id="nnjnj"></ruby></ruby>