Linux服务器中的程序规范和技巧

来源:互联网 发布:nginx tomcat 真实ip 编辑:程序博客网 时间:2024/06/13 02:51

摘自《用 TCP/IP 进行网际互连》、《Linux高性能服务器编程

1.后台运行

  i=fork()

  if(i<0)

  {

printf("%s",strerror(errno))

exit(1);

  }

  if(i)

  {

exit(0);//父进程退出,使得子进程成为后台进程

  }

  ……//子进程被系统初始进程init接管,成为后台进程


2.调用fork后子进程关闭所有继承的文件

  for(i=getdtablesize();i>=0;i++)//或者i=NOFILE ;NOFILE是一个进程最多打开的文件数

  {

close(i);

  }


3.为了确保用户终端的信号不影响后台服务器程序运行,应该将服务器和控制终端分离

  if( ( fd=open("/dev/tty",O_RDWR) )>=0 )

  {

ioctl(fd,TIOCNOTTY,0);

close(fd);

  }

也可以用pid_t setsid()函数来创建新的会话和新进程组并使此进程成为新会话、新进程组的领导、与控制台分离,如果此进程已经是一个进程组领导了就错误返回-1


4.服务器应该移到一个已知目录下,在那里它可以一直运行下去而不影响正常的系统管理活动

#include <unistd.h>

int chdir(const char* path);//更改工作目录---chdir("/"),chdir("/temp")

int chroot(const char* path);//更改进程的根目录,修改后就可能访问不到/dev这些文件或目录,但是更改前打开的文件描述仍然有效,此外只有特权进程才能更改根目录


5.用户权限-设置掩码umask

  a. umask(027);//拿走权限

   http://baike.sogou.com/v54497252.htm

对于umask值0 0 2,相应的文件和目录缺省创建权限是什么呢?

第一步,我们首先写下具有全部权限的模式,即777 (所有用户都具有读、写和执行权限)。

第二步,在下面一行按照umask值写下相应的位,在本例中是0 0 2。

第三步,在接下来的一行中记下上面两行中没有匹配的位。这就是目录的缺省创建权限。

稍加练习就能够记住这种方法。

第四步,对于文件来说,在创建时不能具有执行权限,只要拿掉相应的执行权限比特即可。

这就是上面的例子, 其中u m a s k值为0 0 2:

1) 文件的最大权限 rwx rwx rwx (777)

2) umask值为0 0 2 --- --- -w-

3) 目录权限 rwx rwx r-x (775) 这就是目录创建缺省权限

4) 文件权限 rw- rw- r-- (664) 这就是文件创建缺省权限

下面是另外一个例子,假设这次u m a s k值为0 2 2:

1) 文件的最大权限 rwx rwx rwx (777)

2 ) u m a s k值为0 2 2 --- -w- -w-

3) 目录权限 rwx r-x r-x (755) 这就是目录创建缺省权限

4) 文件权限 rw- r-- r-- (644) 这就是文件创建缺省权限

b.一个进程有两个用户id:uid(运行程序的用户,真实用户)和euid(有效id)

real user ID (uid): 实际用户ID,指的是进程执行者是谁
effective user ID (euid): 有效用户ID,指进程执行时对文件的实际访问权限
saved set-user-ID (saved uid): 保存设置用户ID。是进程刚开始执行时,euid的副本。在执行exec调用之后能重新恢复原来的effectiv user ID.
上面这三个ID是相对于进程而言的.

set-user-ID (suid)/set-group-ID(sgid):设置用户ID,这是相对于文件来说的.设置了set-user-ID位的可执行程序,执行时,进程的effective user ID与saved set-uesr-ID都为程序文件所属用户的ID. 时real user ID与effective user ID就不一定相等了.这类程序称之为SUID程序,这类程序有特殊的用途.典型的例子:passwd程序,ping程序等

6.服务器进程离开原先父进程的进程组

   setpgrp(0,getpid());


7.重定向标准输入输出、错误输出

  fd=open("/dev/null",O_RDWR);

  dup(fd);

  dup(fd);


8.只允许一个副本运行

#define LockFile "/usr/spool/lockfile.lock"

fd=open(LockFile,O_RDWR|O_CREAT,0640);

if(fd<0)

{

exit(1);

}

if(flock(fd,LOCK_EX|LOCK_NB))

{

printf("只能运行一个");

exit(0)

}


sprintf(buf,"%6d0",getpid());

write(fd,buf,strlen(buf));//使用锁文件记录进程号


9.接收处理每个子进程退出,父进程要是不用wait()等待进程成结束,则子进程默认会变成僵尸进程。但是可以用信号处理

signal(SIGCHLD,dealCHLD);

  deal(int sig)

{

int status;

while(wait3(&status,WNOHANG,0)>=0)

;

}


10.忽略除了几个控制信号(sigkill(9)等) 外 的所有信号

  如:signal(SIG_IGN,SIGHUP)


11.使用日志rsyslogd

 初始化 openlog("myprog",LOG_PID,LOG_UER);//可以不初始化,默认是LOG_UER--void openlog(const char *ident, int option, int facility);

syslog(LOG_DEBUG,"my program debuging ");//写日志

closelog();


int setlogmask(int maskpri);//设置日志掩码,使日志级别大于日志掩码的日志信息被系统忽略-如调试信息

   

0 0