Posts Linux高性能服务器编程--服务器编程规范
Post
Cancel

Linux高性能服务器编程--服务器编程规范

1. 日志函数 syslog

syslog

2. 用户信息

UID(真实用户ID) 与 EUID(有效用户ID)

  • 为什么引入EUID(有效用户id)? 允许不同的用户以UID的权限运行改程序。设置set-user-id字段,任何用户启动该程序,其有效用户就是该程序的所有者

demo 切换用户

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/*
 * 以root身份启动的进程切换为一个普通用户身份运行
 */
static bool switch_to_user( uid_t user_id, gid_t gp_id )
{
    // 先确保目标用户不是root
    if ( ( user_id == 0 ) && ( gp_id == 0 ) )
    {
        return false;
    }
    //确保当前用户是合法用户
    gid_t gid = getgid();
    uid_t uid = getuid();
    if ( ( ( gid != 0 ) || ( uid != 0 ) ) && ( ( gid != gp_id ) || ( uid != user_id ) ) )
    {
        return false;
    }
    // 如果不是root 则已经是目标用户
    if ( uid != 0 )
    {
        return true;
    }
    // 切换到目标用户
    if ( ( setgid( gp_id ) < 0 ) || ( setuid( user_id ) < 0 ) )
    {
        return false;
    }

    return true;
}

3. 进程间的关系

  • 进程组 Linux 下每个进程都属于一个进程组,因此除了PID信息外,还有进程组ID PGID. 每个进程组都有一个首领进程,其PGID 与 PID 相同。进程组将一直存在,直到其中所有的进程都退出。 一个进程只能设置自己或其子进程的PGID。

    1
    2
    
      int setpgid(pid_t pid, pid_t pgid); // 设置pgid
      int gettpgid(pid_t pid, pid_t pgid); // 获得pgid
    
  • 会话 脱离父进程pid_t setsid(void) 用于创建一个会话,该函数不能由进程组的首领进程调用
    • 调用的进程会成为会话的首领。
    • PGID 就是调用进程的PID
  • 用ps命令查看进程间关系

    命令: ps -o pid,ppid,pgid,sid,comm | less

    1
    2
    3
    4
    
      PID  PPID  PGID   SID COMMAND
      824 24456   824 24456 ps
      825 24456   824 24456 less
      24456 24455 24456 24456 bash
    

4.系统资源限制

p120

1
2
    int getrlimit(int resource, struct rlimit *rlim);
    int setrlimit(int resource, const struct rlimit *rlim);

5. 改变工作目录

1
2
char* getcwd(char *buf,size_t size); // 获取当前目录
chdir()  // 改变工作目录

6. 服务器后台化

在代码中让一个进程以守护进程的方式运行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
bool daemonize(){
    // 创建子进程 关闭父进程 这样可以使得程序在后台运行
    pid_t pid = fork();
    if (pid < 0)
        return false;
    else if (pid > 0)
        exit(0);

    // 设置文件权限掩码  一般配合create file 使用
    umask(0);

    // 新建会话 设置本进程为进程组的首领
    pid_t sid = setsid();
    
    // 切换工作目录
    if ((chdir("/")) < 0){
        return false;
    }
    
    // 关闭标准输入 标准输出 标准错误输出
    close(STDIN_FILENO);
    close(STDOUT_FILENO);
    close(STDERR_FILENO);
    
    // 将标准输入 输出 error 重定向到 /dev/null 文件
    open("/dev/null",O_RDONLY);
    open("/dev/null",O_RDWR);
    open("/dev/null",O_RDWR);
}
This post is licensed under CC BY 4.0 by the author.

Contents

Trending Tags