Linux 服務器程序規范、服務器日志、用戶、進程間的關系

文章目錄

  • 服務器程序規范
  • 日志
    • rsyslogd 守護進程
    • syslog函數
    • openlog函數
    • setlogmask函數
    • closelog函數
  • 用戶
  • 進程間的關系
    • 進程組
    • 會話
    • 系統資源限制
    • 改變工作目錄和根目錄
    • 服務器程序后臺化


服務器程序規范

  1. Linux 服務器程序一般以后臺進程(守護進程[daemon])形式運行。它沒有控制終端,因此不會意外接受到用戶輸入,守護進程的父進程通常是 init 進程(PID為1)。
  2. 服務器的調試和維護都需要一個專業的日志系統,Linux 常用一個守護進程 rsyslogd(syslogd的升級版) 來處理系統日志。
  3. Linux 服務器程序一般以 非root 的身份運行。如:mysqldhttpdsyslogd 等后臺進程分別擁有自己的運行賬戶 mysqlapachesyslog
  4. Linux 服務器程序通常能處理很多命令行選項,如果一次運行的選項太多,那么可以用配置文件來管理。配置文件一般放在 /etc 目錄下。
  5. Linux 服務器程序通常在啟動時會生成一個記錄該后臺進程 PID 的文件并存入 /var/run 目錄中。例如: syslogdPID 文件是 /var/run/syslogd.pid

日志

rsyslogd 守護進程

既能接受用戶進程輸出的日志,也能接受內核日志。

  • 用戶進程調用 syslog函數 將日志輸出到一個 UNIX 本地域 socket 類型(AF_UNIX)的文件 /dev/log 中,rsyslogd 則監聽該文件以獲得用戶進程的輸出。
  • 內核日志由 printk 等函數打印至內核的 環狀緩存(ring buffer) 中,環狀緩存的內容直接映射到 /proc/kmsg 中,rsyslogd 讀取該文件以獲得內核日志。

在這里插入圖片描述


syslog函數

應用程序通過 syslog函數rsyslogd 守護進程通信:

#include<syslog.h>
void syslog( int priority, const char* message, ...);
// 采用可變參數(message 和 第三個參數……)來結構化輸出
// priority:設施值與日志級別的按位或,設施值的默認值是 LOG_USER。

限于 LOG_USER 設施值對應的日志級別有:

#include<syslog.h>
#define LOG_EMERG    0 // 系統不可用
#define LOG_ALERT    1 // 報警,需要立即采取動作
#define LOG_CRIT     2 // 非常嚴重的狀況
#define LOG_ERR      3 // 錯誤
#define LOG_WARNING  4 // 警告
#define LOG_NOTICE   5 // 通知
#define LOG_INFO     6 // 信息
#define LOG_DEBUG    7 // 調試

openlog函數

改變 syslog 的默認輸出方式,進一步結構化日志內容:

#include<syslog.h>
void openlog( const char* ident, int logopt, int facility );
// ident指定的字符串被添加到日志消息的日期和時間之后,通常被設置為程序的名字
// logopt對 syslog 調用的行為進行配置,為下列值的按位或:
#define LOG_PID     0x01 // 在日志消息中博阿寒程序 PID
#define LOG_CONS    0x02 // 如果消息不能記錄到日志文件,則打印至終端
#define LOG_ODELAY  0X04 // 延遲打開日志功能知道第一次調用 syslog
#define LOG_NDELAY  0x08 // 不延遲打開日志功能
// facility用來修改 syslog 函數中的默認設施值

setlogmask函數

程序在開發階段可能需要輸出很多調試信息,而發布之后又需要將這些調試信息關閉。

解決這個問題的方法并非是在發布后刪除調試代碼(日后可能還需要用到),而有更簡單的做法——設置日志掩碼,使日志級別大于掩碼日志信息被系統忽略。

setlogmask函數 就用以設置日志掩碼:

#include<syslog.h>
int setlogmask( int maskpri );
// maskpri指定日志掩碼值
// 該函數始終會成功,返回調用進程舊的日志掩碼值

closelog函數

用以關閉日志功能:

#include<syslog.h>
void closelog();

用戶

服務器中不同的用戶有不同的權限,因此 獲取or設置 當前進程的 真實用戶ID(UID)、有效用戶ID(EUID)、真實組ID(GID)、有效組(EGID) 就尤為重要:

#include <sys/types.h>
#include <unistd.h>
uid_t getuid();
uid_t geteuid();
gid_t getgid();
gid_t getegid();
int setuid( uid_t uid );
int seteuid( uid_t uid );
int setgid( gid_t gid );
int setegid( gid_t gid );

一個進程有兩個 用戶ID: UIDEUIDEUID 方便了資源訪問:使得 運行程序的用戶 擁有 該程序的有效用戶 的權限。如:任何用戶都可以通過 su程序 修改自己的賬戶信息,這就不得不訪問需要 root 權限的 /etc/passwd 文件。那么以普通用戶身份啟動的 su程序 如何能訪問/etc/passwd 文件呢?

ls 命令可以查看到,su程序 的所有者是 root,且被設置了 set-user-id標志 ,即任何普通用戶運行 su程序 時,su程序 的有效用戶為 root。有效用戶為 root 的進程被稱為 特權進程(privileged processes)

類似的,EGID 為運行目標程序的組用戶提供有效組的權限。


進程間的關系

進程組

Linux 下每個進程都隸屬于一個進程組,PGID 即為它的 進程組ID。進程組將一直存在,知道其中所有進程都退出或者加入到其他線程組。每個進程組都有一個首領進程,其 PGIDPID 相同。

#include< unistd.h>
pid_t getpgid( pid_t pid );
// 成功返回 ID,失敗返回 -1 并設置 errno
int setpgid( pid_t pid, pid_t pgid );
// 將 PID 為 pid 的進程的 PGID 設置為 pgid,若 pid 和 pgid 相等,則 pid 指定的進程將被設定為進程組首領
// 若 pid=0,則表示設置 當前進程 的 PGID 為 pgid
// 若 pgid=0,則使用 pid 作為目標進程的 PGID 
// 成功時返回 0,失敗返回 -1 并設置 errno

一個進程只能設置自己或者子進程的 PGID,子進程調用 exec 系列函數后,父進程不再能設置它的 PGID


會話

一些有關聯的進程組能形成一個會話session),下面的函數用以創建一個會話:

#include<unistd.h>
pid_t setsid( void );
// 成功時返回新的進程組的 PGID,失敗則返回 -1 并設置 errno

該函數不能由進程組的首領進程調用,否則產生一個錯誤。對于非組首領的進程,創建新會話的同時且有如下額外效果:

  • 調用進程成為會話的首領,此時該進程是新會話的唯一成員。
  • 新建一個進程組,其 PGID 就是調用進程的 PID,調用進程成為該組的首領。
  • 調用進程將甩開終端(如果有的話)。

Linux 進程并未提供所謂 會話ID(SID) 的概念,但將會話首領所在的進程組的 PGID 視為 SID,并提供了如下函數來讀取 SID

#include<unistd.h>
pid_t getsid( pid_t pid );

系統資源限制

Linux 上運行的程序都會受到資源限制的影響,比如物理設備限制(CPU數量、內存數量等)、系統策略限制(CPU時間等),以及具體實現的限制(文件名的最大長度)。這些系統資源限制可以通過下面的函數來讀取設置

#include <sys/resource.h>
int getrlimit( int resource, struct rlimit* rlim );
int setrlimit( int resource, const struct rlimit* rlim );
// 成功時返回 0,失敗時返回 -1 并設置 errno。
struct rlimit{rlim_t rlim_cur; // 指定資源的軟限制,是一個建議性的,最好不要超越的限制,若超越限制,則系統可能向進程發送信號以終止其運行。rlim_t rlim_max; // 指定資源的硬限制,一般是軟限制的上限。普通程序可以減小硬限制,只有以 root 身份運行的程序才能增加硬限制。// rlim_t是一個整數類型,描述資源級別。
};

除上述外:

  • 還可以使用 ulimit 命令修改當前 shell 環境下的資源限制(軟限制或/和硬限制),這種修改將對該 shell 啟動的所有后續程序有效。
  • 還可以通過修改配置文件來改變系統軟限制和硬限制,這種修改是永久的。

改變工作目錄和根目錄

#include<unistd.h>
/* 獲取進程當前工作目錄 */
char* getcwd( char* buf, size_t size );
// buf指向的內存用于存儲進程當前工作目錄的絕對路徑名,大小由 size 參數指定
// 如果當前工作的絕對路徑長度(加上末尾的“\0”)超過了 size,則返回 NULL 并設置 errno 為 ERANGE。
// 若 buf 為 NULL 并且 size 非 0,則 getcwd 可能在內部使用 malloc 動態分配內存,并將進程的當前工作目錄存儲在其中,
// 此時我們需要自己釋放 getcwd 在內部創建的這塊內存。
// 成功返回一個指向目標存儲區(buf指向的緩存區或者getcwd在內部動態創建的緩存區)的指針,失敗返回 NULL 并設置 errno。/* 改變進程的工作目錄 */
int chdir( const char* path );
// path 指定要切換到的目標目錄
// 成功返回 0,失敗返回 -1 并設置 errno/* 改變進程根目錄 */
int chroot(const char* path);
// 參數和返回值同上,調用本函數后,仍需使用 chdir("/") 來將工作目錄切換至新的根目錄。
// 改變進程的根目錄后,程序可能無法訪問處于舊路徑的文件or目錄,
// 不過可以利用進程已經打開的文件描述符來訪問調用 chroot 之后不能直接訪問的文件。
// 只有特權進程才能改變根目錄

服務器程序后臺化

讓一個進程以守護進程的方式運行:

#include<unistd.h>
int daemon(int nochdir, int noclose);
// nochdir 用于指定是否改變工作目錄,為 0 則工作目錄被設置為“/”(根目錄),否則繼續使用當前目錄
// noclose 為 0 時,標準輸入、輸出、錯誤輸出都被重定向到 /dev/null 文件,否則依然使用原來的設備
// 成功返回 0,失敗返回 -1 并設置 errno

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/443724.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/443724.shtml
英文地址,請注明出處:http://en.pswp.cn/news/443724.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

IO模型 :阻塞IO、非阻塞IO、信號驅動IO、異步IO、多路復用IO

文章目錄IO模型阻塞IO非阻塞IO信號驅動IO多路復用IO異步IOIO模型 根據各自的特性不同&#xff0c;IO模型被分為阻塞IO、非阻塞IO、信號驅動IO、異步IO、多路復用IO五類。 最主要的兩個區別就是阻塞與非阻塞&#xff0c;同步與異步。 阻塞與非阻塞 阻塞與非阻塞最主要的區別就…

Tomcat服務器集群與負載均衡實現

一、前言 在單一的服務器上執行WEB應用程序有一些重大的問題&#xff0c;當網站成功建成并開始接受大量請求時&#xff0c;單一服務器終究無法滿足需要處理的負荷量&#xff0c;所以就有點顯得有點力不從心了。另外一個常見的問題是會產生單點故障&#xff0c;如果該服務器壞掉…

Linux服務器 | 事件處理模式:Reactor模式、Proactor模式

文章目錄Reactor模式Proactor模式同步I/O模型模擬Proactor模式兩者的優缺點ReactorProactor同步I/O模型通常用于實現 Reactor 模式&#xff0c;異步I/O模型通常用于實現 Proactor 模式。&#xff08;不是絕對的&#xff0c;同步I/O也可模擬出 Proactor 模式&#xff09; React…

Linux服務器 | 服務器模型與三個模塊、兩種并發模式:半同步/半異步、領導者/追隨者

文章目錄兩種服務器模型及三個模塊C/S模型P2P模型I/O處理單元、邏輯單元、存儲單元并發同步與異步半同步/半異步模式變體&#xff1a;半同步/半反應堆模式改進&#xff1a;高效的半同步/半異步模式領導者/追隨者模式組件 &#xff1a;句柄集、線程集、事件處理器工作流程兩種服…

香農信息熵之可憐的小豬

文章目錄題目解析香農熵公式樣例具體分析代碼題目 有 n 桶液體&#xff0c;其其中 正好 有一桶含有毒藥&#xff0c;其裝的都是水。它們從外觀看起來都一樣。為了弄清楚哪只水桶含有毒藥&#xff0c;你可以喂一些豬喝&#xff0c;通過觀察豬是否會死進行判斷&#xff0c;實驗對…

字符串匹配之KMP(KnuthMorrisPratt)算法(圖解)

文章目錄最長相等前后綴next數組概念代碼實現圖解GetNext中的回溯改進代碼實現代碼復雜度分析最長相等前后綴 給出一個字符串 ababa 前綴集合&#xff1a;{a, ab, aba, abab} 后綴集合&#xff1a;{a, ba, aba, baba} 相等前后綴 即上面用同樣顏色標識出來的集合元素&#…

linux下tomcat6.0與jdk安裝詳細步驟

安裝Tomcat6.0和JDK1.6 在linux系統上安裝tomcat和jdk應該說是我學習linux知識的第一課了&#xff0c;之前只 是聽說過&#xff0c;從沒接觸過&#xff0c;但我們公司項目都是部署在linux系統上的&#xff0c;那天上司突 然給我發了幾個文檔&#xff0c;讓我看一下&#xff…

Android入門(一) | Android Studio的配置與使用

文章目錄安裝配置Android Studio使用Android Studio模擬器更改Android SDK的路徑Hello World&#xff01;安裝配置Android Studio 從這一步開始&#xff1a; 一直點 next 即可&#xff0c;直到存儲路徑的選擇上&#xff0c;可以放到非 C 盤&#xff0c;這里我放到 D 盤了&am…

Android 入門(四) | Intent 實現 Activity 切換

文章目錄Intent顯式 Intent定義兩個 xml 文件android:orientationmatch_parent 和 wrap_contentIntent函數定義兩個 Activity隱式 Intent更多隱式 Intent 的用法用隱式 Intent 打開系統瀏覽器自建 Activity 以響應打開網頁的 Intent向下一個活動傳遞數據返回數據給上一個活動In…

Android入門(二) | 項目目錄及主要文件作用分析

文章目錄項目目錄分析app目錄分析AndroidManifest.xml 分析MainActivity.kt 分析build.gradle 分析最外層目錄下的 build.gradleapp 目錄下的 build.gradle項目目錄分析 我們來看一下 src/main/res 下的一些文件&#xff1a; .gradle 和 .idea &#xff1a;這兩個目錄下放置…

Android入門(三) | Android 的日志工具 Logcat

文章目錄日志工具類 android.util.LogLogcat 中的過濾器日志工具類 android.util.Log Log 從屬日志工具類 android.util.Log &#xff0c;該類提供了五個方法供我們打印日志&#xff1a; Log.v() &#xff1a;用于打印那些最為瑣碎的、意義最小的日志信息。對應級別 verbose&…

Android 客戶端與服務器交互方式

突然想到一個問題就是Android客戶端與服務器交互有幾種方式&#xff0c;因為在腦袋里想當然的就是webservices和json。要在Android手機客戶端與pc服務器交互&#xff0c;需要滿足下面幾種條件&#xff1a;跨平臺、傳輸數據格式標準、交互方便...。 為了與服務器通訊其實無非就…

Android入門(五) | Activity 的生命周期

文章目錄Activity 的狀態及生命周期實現管理生命周期FirstActivitySecondActivityDialogActivity運行結果舊活動被回收了還能返回嗎&#xff1f;Activity 的狀態及生命周期 Android 的應用程序運用 棧&#xff08;Back Stack&#xff09; 的思想來管理 Activity&#xff1a; …

Android入門(六) | Activity 的啟動模式 及 生產環境中關于 Activity 的小技巧

文章目錄Activity 的啟動模式standardsingleTopsingleTasksingleInstance技巧了解當前界面是哪個 Activity隨時隨地退出程序啟動活動的最佳寫法Activity 的啟動模式 standard&#xff1a;默認的啟動方式&#xff0c;每次啟動一個活動都會重新創建singleTop&#xff1a;如果該活…

Android入門(七) | 常用控件

文章目錄TextView 控件&#xff1a;文本信息Button 控件&#xff1a;按鈕EditText 控件&#xff1a;輸入框ImageView 控件&#xff1a;圖片ProgressBar 控件&#xff1a;進度條AlertDialog 控件&#xff1a;提示框ProgressDialog 控件&#xff1a;帶有進度條的提示框TextView 控…

Android入門(八) | 常用的界面布局 及 自定義控件

文章目錄LinearLayout &#xff1a;線性布局android:layout_gravity &#xff1a;控件的對齊方式android:layout_weight&#xff1a;權重RelativeLayout &#xff1a;相對布局相對于父布局進行定位相對于控件進行定位邊緣對齊FrameLayout &#xff1a;幀布局Percent &#xff1…

Android入門(九)| 滾動控件 ListView 與 RecyclerView

文章目錄ListView內置類型的簡單運用定制數據類型提升效率點擊事件RecyclerView布局管理器點擊事件ListView 內置類型的簡單運用 由于手機屏幕空間有限&#xff0c;能夠一次性在屏幕上顯示的內容不多&#xff0c;當我們的程序有大量數據需要顯示的時候就可以借助 ListView 來…

關于“三門問題”的一些想法

三門問題&#xff08;Monty Hall problem&#xff09;亦稱為蒙提霍爾問題、蒙特霍問題或蒙提霍爾悖論&#xff0c;大致出自美國的電視游戲節目Let’s Make a Deal。問題名字來自該節目的主持人蒙提霍爾&#xff08;Monty Hall&#xff09;。參賽者會看見三扇關閉了的門&#xf…

Android入門(10)| Fragment碎片詳解

文章目錄為什么要使用碎片&#xff08;Fragment&#xff09;實例布局文件FragmentActivity動態添加碎片布局文件FragmentActivity碎片通信Fragment布局文件Activity生命周期為什么要使用碎片&#xff08;Fragment&#xff09; 我們在手機上看新聞可能是這樣的&#xff1a; Re…

Android開發(1) | Fragment 的應用——新聞應用

文章目錄Item&#xff1a;標題子項布局文件Java代碼標題碎片布局文件Java代碼新聞內容碎片布局文件Java代碼新聞內容活動布局文件Java代碼首界面布局文件Java代碼Item&#xff1a;標題子項 布局文件 news_item.xml&#xff1a; <TextViewxmlns:android"http://schema…