当前位置: 首页 > news >正文

Linux 服务器程序规范——《Linux高性能服务器编程》第7章——读书笔记

1、概述

在这里插入图片描述

2、日志

2.1 Linux 系统日志

Linux使用一个守护进程(后台进程)rsyslogd来处理系统日志。

Linux系统产生的日志大概可以分为两种,内核日志 和 用户进程输出的日志。

  • ① 用户进程调用syslog函数生成(系统)日志,该函数把日志输出到/dev/log文件中,rsyslogd监听该文件 并获取用户进程的输出,把他们输出到特定的日志文件(/var/log/*文件)。
  • ② 内核日志由printk等函数打印至内核的环状缓存中,环状缓存的内容直接映射到/proc/kmsg文件中。rsyslog通过读取该文件获得内核日志,把他们输出到特定的日志文件(/var/log/*文件)。
    在这里插入图片描述

2.2 syslogopenlogcloselog函数

① 用途

记录日志。Linux C提供一套日志写入接口,就是他们仨。
openlog可选的,若不调用openlog,则在第一次调用syslog时,自动调用openlogcloselog也是可选的,它用于关闭syslog日志功能(关闭与syslog守护进程通信的描述符)。

openlog函数

openlog用于打开一个到系统日志记录程序的连接,打开之后就可以用syslog向系统日志里添加信息了。此外,该函数还能改变syslog的默认输出方式(其facility参数)。而closelog就是用于关闭此连接。openlog定义如下:

#include<syslog.h>
void openlog(const char* ident, int logopt, int facility);
  • ident所表示的字符串通常就是当前程序的名字,它固定的加在每行日志消息的日期和时间之后,以作为标记。调用openlog指定一个ident后,此ident会被加到每行日志消息中。
  • logopt参数对后续调用的 syslog函数的行为进行控制(或配置),它可取下列值的按位或与在这里插入图片描述
  • facility指明记录日志的程序(后续的syslog函数)的类型。
    另一种解释:facility参数用来修改syslog函数中的默认设施值。
    我们在讨论syslog函数的时候讨论设施值的含义及其具体取值。

syslog函数

开启日志功能。syslog函数用于把日志消息发送给系统程序rsyslogd去记录。也就是:用于程序使用syslog函数rsyslogd守护进程通信syslog函数的定义如下:

#include<syslog.h>
void syslog(int priority, const char* message, ...);	该函数采用可变参数(第二个'message'和第三个参数'...'
  • priority表示消息的紧急级别。它的值是设施值日志级别按位或与。其中,设施值的默认值是LOG_USER ,下面的讨论也只限于这一种设施值。日志级别的值如下:在这里插入图片描述
  • 第二个参数是一个格式化表达式,第三个参数是格式化表达式对应的参数,两个参数共同结构化输出。(这两个参数的关系,就类似于printf函数的两个参数那样)

closelog函数

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

关闭日志功能。

⑤ 日志过滤——setlogmask函数

在这里插入图片描述

3、用户信息

什么是用户ID,什么是组ID
其他用户:陌生的用户,不属于当前的用户组。

3.2 UID、EUID、GID 和 EGID 都是啥

① UID:实际用户ID

登陆时候的ID。当一个用户登陆到这个系统后就唯一确定了他的UID。(实际用户组ID类似)
该值在login函数执行时,取自口令文件/etc/passwd中,一般由用户标识号(第三列)标识。这个ID在登陆期间一般不会改变,除非有root权限用setuid改变。

② EUID:有效用户ID

有效ID就是用于权限检查的ID

③ GID:实际组ID

一个用户登录时其所属的组ID。

④ EGIO:有效组ID

有效组ID就是用于权限检查的组ID

3.3 获取和设置当前进程的 上面四种ID

在这里插入图片描述

3.4 特权进程

有效用户为root的进程称为特权进程。

3.5 set-user-id标志

这个标志表示,任何普通用户运行 设置了该标志的程序时,其有效用户就是该程序的所有者

sudo chmod +s 文件名			设置文件的 set-user-id 标志

4、切换用户

下面的代码将以root身份启动的进程切换为 普通用户身份运行:

static bool switch_to_user(uid_t user_id, git_t gp_id)
{
	/* 先确保目标用户不是root */
	if (user_id == 0 && gp_id == 0)
	{
		return false;
	}
	
	/* 确保当前用户是合法淞沪:root 或者目标用户 */
	git_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;
}

这个代码等以后用到的时候再来看吧,现在不明所以,先不管了。

5、进程间关系

5.1 进程组

在这里插入图片描述

在这里插入图片描述

5.2 会话

在这里插入图片描述
在这里插入图片描述

5.3 用ps命令查看进程关系

在这里插入图片描述

6、系统资源限制

Linux上运行的程序都会受到资源限制的影响,比如物理设备闲置(CPU数量、内存数量等)、系统策略限制(CPU时间等),以及具体实现的限制(比如文件名的最大长度)。Linux系统资源限制可以通过如下一对函数来读取设置

#include<sys/resource.h>
int getrlimit(int resource, struct rlimit* rlim);
int setrlimit(int resource, const struct rlimit* rlim);

rlim参数是指向rlimit结构体类型的指针,rlimit结构体定义如下:

struct rlimit
{
	rlim_t rlim_cur;
	rlim_t rlim_max;
};

在这里插入图片描述

7、改变工作目录 和 根目录

在这里插入图片描述

获取进程当前工作目录改变进程工作目录的函数分别是:

#include<unistd.h>
char* getcwd(char* buf, size_t size);
int chdir(const char* path);

getcwd

参数:
buf参数指向的字符串 存储了进程当前工作目录的绝对路径名,其大小由size参数指定

  • ——若绝对路径长度(还要加上空字符\0超过了size,则getcwd返回NULL,并设置errnoERANGE
  • ——若 buf为NULL,并且 size非0,则getcwd可能在内部使用malloc动态分配内存,并将当前工作目录的绝对路径存在其中。如果是这种情况,我们必须自己释放getcwd在内部创建的这块内存

返回值:
getcwd函数成功时返回一个指向目标存储区的指针buf指向的缓存区或是getcwd动态创建的缓存区),失败返回BULL并设置errno

chdir

chdir函数的path参数指定要切换到的目标目录。成功时返回0,失败返回-1并设置errno

改变进程根目录的函数是chroot

#include<unistd.h>
int chroot(const char* path);

path参数指定要切换到的目标根目录。成功返回0,失败返回-1并设置errno
在这里插入图片描述
chroot就是把当前程序所在的路径整个 直接变成新的根目录。举个例子:现在有个.c源文件,他的路径是/home/xl22/桌面/trash/chroot.c,其中trash目录的其他内容如下:

.
|-- chroot.c
|-- chroot.out
`-- test
    `-- 111.txt

文件111.txt的路径是:/home/xl22/桌面/trash/test/111.txt
如果在chroot.c中进行了如下调用:

chroot("./test");

那么新的111.txt的路径变为:/111.txt,也就是包括test在内的前面多有路径一起被替换为了根目录,即/

如果只想把test文件夹之前的部分更改为根目录,那么chroot.c文件中的调用如下:

chroot("./");

注:使用chroot函数的程序必须是特权进程,否则该函数会调用失败,所以,当该函数调用失败的时候先检查你有没有超级权限。

8、服务器程序后台化

在这里插入图片描述
在这里插入图片描述
上面的函数能够让一个程序在后台运行
Linux提供了完成同样功能的函数:

#include<ubistd.h>
int deamon(int nochdir, int noclose);
  • nochdir参数用于指定是否改变工作目录。
    ——若给他传递0,则工作目录被设置为根目录/,否则继续使用当前工作目录。
  • noclose参数为0时,标准输入、标准输出和标准错误输出都被重定向到dev/null文件,也就是不输出任何信息,否则仍然照样输出。

deamon调用了fork,如果fork成功,那么父进程就调用_exit(2)退出,所以看到的错误信息 全部是子进程产生的。
deamon如果成功返回0,失败返回-1并设置errno

相关文章:

  • 高性能服务器程序框架——《Linux高性能服务器编程》第8章——读书笔记
  • 触发EPOLLIN 和 EPOLLOUT的所有情况
  • 红黑树(rbtree)、以及epoll的实现原理
  • epoll 的 ET,LT工作模式———实例程序
  • epoll 的EPOLLONESHOT 事件———实例程序
  • select 同时接收普通数据 和 带外数据
  • I/O复用的高级应用之一:非阻塞 connect———使用 select 实现(也可以用 poll 实现)
  • I/O复用的高级应用:同时处理 TCP 和 UDP 服务
  • I/O复用的高级应用:聊天室程序———实例代码
  • select、poll、epoll的使用方法 和 使用场景
  • 使用统一事件源的方式同时处理信号和 I/O
  • 使用SIGURG信号接受带外数据
  • 信号 ——《Linux高性能服务器编程》第10章——读书笔记
  • Linux 文件I/O 及其 多个相关函数
  • python——学校课程预习+复习
  • [译] 怎样写一个基础的编译器
  • 【翻译】babel对TC39装饰器草案的实现
  • 【译】理解JavaScript:new 关键字
  • 2019.2.20 c++ 知识梳理
  • - C#编程大幅提高OUTLOOK的邮件搜索能力!
  • CentOS7 安装JDK
  • Codepen 每日精选(2018-3-25)
  • java第三方包学习之lombok
  • Nginx 通过 Lua + Redis 实现动态封禁 IP
  • underscore源码剖析之整体架构
  • 从PHP迁移至Golang - 基础篇
  • 大数据与云计算学习:数据分析(二)
  • 给初学者:JavaScript 中数组操作注意点
  • 更好理解的面向对象的Javascript 1 —— 动态类型和多态
  • 力扣(LeetCode)22
  • 你真的知道 == 和 equals 的区别吗?
  • 前端js -- this指向总结。
  • 微信小程序填坑清单
  • 消息队列系列二(IOT中消息队列的应用)
  • 小程序、APP Store 需要的 SSL 证书是个什么东西?
  • 阿里云IoT边缘计算助力企业零改造实现远程运维 ...
  • ​LeetCode解法汇总2808. 使循环数组所有元素相等的最少秒数
  • ​ssh-keyscan命令--Linux命令应用大词典729个命令解读
  • ​总结MySQL 的一些知识点:MySQL 选择数据库​
  • # 执行时间 统计mysql_一文说尽 MySQL 优化原理
  • (06)Hive——正则表达式
  • (10)Linux冯诺依曼结构操作系统的再次理解
  • (9)YOLO-Pose:使用对象关键点相似性损失增强多人姿态估计的增强版YOLO
  • (C语言)字符分类函数
  • (附源码)python房屋租赁管理系统 毕业设计 745613
  • (附源码)springboot 智能停车场系统 毕业设计065415
  • (转) 深度模型优化性能 调参
  • (转)C#调用WebService 基础
  • (转载)跟我一起学习VIM - The Life Changing Editor
  • (转载)虚函数剖析
  • *p++,*(p++),*++p,(*p)++区别?
  • .a文件和.so文件
  • .net core 微服务_.NET Core 3.0中用 Code-First 方式创建 gRPC 服务与客户端
  • .NET Core/Framework 创建委托以大幅度提高反射调用的性能
  • .Net Core和.Net Standard直观理解