服务器程序除了网络通信之外,还要考虑很多其他的细节,比较零散,但基本都是模板式的。Linux服务器程序一般在后台运行。后台程序也称为守护进程。它没有控制终端,因此不会意外接受用户输入。守护进程的父进程一般是init进程(pid=1)。Linux服务器程序通常都有一个日志系统,至少可以将日志输出到文件中,一些高级的服务器可以将日志输出到专用的UDP服务器上。大多数后台进程在/var/log下都有自己的日志目录。Linux服务器程序通常以专用的非根身份运行。mysqld、httpd、syslogd等后台进程,分别有自己的运行账号mysql、apache、syslog。'Linux服务器通常是可配置的。服务器程序通常处理许多命令选项。如果一次运行的选项太多,CLA使用配置文件来管理它们。大多数服务器程序都有配置文件并存储在/etc下。Linux服务器程序通常在启动时会生成一个PID文件,存放在/var/run目录下,用于记录后台进程的PID。Linux服务器程序通常需要考虑系统资源和限制来预测它们可以承受多少负载,例如进程可用的文件描述符总数和内存总量。01日志1、Linux系统日志:Linux提供了一个守护进程来处理系统日志——syslogd,升级版——rsyslogd。rsyslogd守护进程可以接收用户进程输出日志,也可以接受内核日志。用户进程通过调用syslog函数产生系统日志。该函数将日志输出到一个unix本地域套接字类型(AF_UNIX)文件/dev/log,rsyslogd监听这个文件获取用户进程的输出。内核日志记录在以前的系统上由另一个守护进程rklogd和rsyslogd管理,它通过附加模块实现了相同的功能。内核日志通过printk等树打印到内核环缓冲区。环形缓存的内容直接映射到/proc/kmsg。rsyslogd通过读取文件获取内核日志。默认调试信息保存在/var/log/debug,一般信息保存在/var/log/messages,内核信息:/var/log/kern.log。配置文件:/etc/rsyslog.conf,主要设置内核日志输入路径,是否接受UDP日志,及其监听端口(默认514/etc/services)是否接受TCP日志及其监听端口,日志文件权限,以及哪些配置包含在文档中。2.syslog()应用程序使用syslog()与守护程序rsyslogd通信。该函数采用可变参数(第二个参数消息和第三个参数......)来构造输出。优先级:设施值(按位异或)日志级别。默认设施值:LOG_USER,下面讨论默认设施值的日志级别。2.1下面的函数可以改变syslog默认的输出方式,进一步结构化日志内容(1)ident:在日志信息的日期和时间之后添加指定的字符串,通常设置为程序名。(2)logopt:配置后续syslog调用的行为,它可以对以下值进行按位异或(3)facility:用于修改ysyslog的默认facility值另外,日志过滤也很重要,和程序在重新开发阶段可能需要输出很多调试信息,而在release之后,我们要关闭这些调试信息。解决这个问题的办法不是在程序发布后删除调试代码(以后可能会用到),而是抓取但是设置日志掩码,这样日志级别大于日志掩码的日志就被被系统忽略。2.2以下函数用于设置syslog的日志掩码。maskpri:指定日志掩码值,该函数总是返回成功,它返回调用进程之前的日志掩码值。2.3关闭日志功能:02用户信息1.UID、EUID、GID、EGID用户信息对于服务器安全非常重要。大部分都说服务器以root启动,不用root运行。基础知识:一个进程有两个用户ID,UID,EUID,EUID的目的是方便访问资源。使运行程序的用户拥有程序的有效用户权限。比如su是用来修改账户信息的,但是在修改账户的时候,su程序的所有者是root。使用su程序时,它的有效用户是程序的所有者root。有效用户为root的进程称为特权进程。EGID类似于EUID。下面演示uid和euid的区别:将生成的可执行文件的属主设置为root,并设置文件set-user-id标志,然后运行。从测试输出来看,进程的uid为启动程序的用户id,euid为root。二、切换用户03进程间关系1、进程组:Linux下的每个进程都属于一个进程组,所以它们除了pid之外,还有一个进程组ID(PGID)。我们使用下面的函数来获取指定进程组的PGID。如果成功,它会返回pid,如果失败-1,它会设置errno。如果pid与pgid相同,则将pid指定的进程设置为进程组组长:如果pid为0,则表示当前进程的PGID为pgid;如果pgid为0,则pid用作目标pgid。setpid函数在成功时返回0,在失败时返回-1,并设置errno。一个进程只能设置自己或其子进程的PGID。而且,当子进程调用exec系列函数时,我们不能再在父进程中为其设置PGID。2.Session(1)一些相关的进程会组成一个session。以下函数用于创建会话:该函数不能被进程组的leader进程调用,否则会产生错误。对于非leader进程,调用该函数不仅会创建一个新的session,还有以下附加效果。调用进程成为会话的领导者,此时它是新会话的唯一成员。新建一个进程组,其PGID为调用进程的PID,调用进程成为组长。调用进程将抛出终端(如果有的话)。该函数成功返回新进程组PGID,失败返回-1,errno。Linux进程没有提供所谓sessionID的概念,但Linux系统认为它等于sessionleader所在进程组的PGID,(2)并提供如下函数读取SID3。使用ps命令查看进程关系执行ps命令查看进程、进程组和会话的关系。ps和less命令是在bash_shell下执行的,所以ps和less命令的父进程是bash命令,从PPID(父进程PID)一栏可以看出。这三个命令创建一个会话(SID为2962)和两个进程组(PGID:2962、3102)。bash命令的PID,PGID和SID是一样的,显然是session的leader,也就是group2962的leader。ps是3102的龙头,04系统资源限制运行在Linux上的程序会受到资源限制的影响,比如物理设备限制(cpu数量,内存数量等),系统策略限制(cup时间等),以及具体实现限制(filename***length)Linux系统资源限制可以通过下面这对函数来读取和设置:getrlimit,setrlimitrlimit结构体定义如下:成功返回0,失败-1,设置errnorlim_t为整型,描述资源级别rlim_cur成员指定了资源的软限制,建议不能超过。如果超出限制,系统可能会向进程发送信号并终止操作。如果当前进程CPU时间超过软限制,系统会向进程发送SIGXCPU信号;当文件大小超过其软限制时,系统将向进程发送SIZEXFSZ信号。rlim_max成员指定资源的硬限制。硬限制一般是软限制的上限。普通程序可以降低限制,但只有以root身份运行的程序才能提高硬限制。另外,我们可以使用ulimit命令来修改当前shell环境下的资源限制(soft/hard)。这个修改对后续所有shell启动的程序都有效,而且我们还可以通过修改配置文件来改变系统软限制和应用限制,这个修改是最好的。05改变工作目录和根目录有些服务器程序需要改变工作目录和根目录(web/var/www)获取当前进程工作目录,改变进程的工作目录:buf指向的内存参数用于存放当前工作目录的绝对路径,size指定其大小如果当前目录的绝对路径超过size(+1('')),getcwd返回NULL,errno:ERANG。chdir中的路径指向要切换到的目录。0表示成功,-1表示失败并设置errno。更改进程根目录:chrootchroot不会更改进程的当前工作目录。调用chroot后,还需要调用chdir("/")将工作转移到新的工作目录,然后原来的文件描述符仍然生效。因此,前面打开的文件描述符可以用来访问调用chroot后不能直接访问的文件(目录)。按照特定步骤操作,示例如下。其实linux提供了一个库函数来完成同样的功能:nochdir:如果传0,工作目录将被设置为“/”,否则继续使用当前工作目录。noclose:传递0个标准输入输出,标准错误输出重定向到dev/null,否则继续使用原来的设备,成功为0,失败为-1并设置error。
