服务端编程基础
1.基础函数及其头文件
#include <unistd.h>
void usleep(usecond)
2.信号
SIGHUP 控制终端的挂起信号
SIGINT 键盘输入退出信号(Ctrl + C)
SIGQUIT 键盘输入退出信号(Ctrl + \)
SIGKILL*
SIGSTOP*
SIGPIPE 管道中止,当写入无人读取的管道时产生该信号,默认终止进程
SIGCHLD 子进程结束或者停止时发送
SIGALARM 定时器信号,以秒为单位,默认终止进程对应这alarm()函数
SIGUSR1/SIGUSR2 自定义,默认终止进程
注:标记*的信号不能被忽略
SIGPIPE:网络程序必须要处理SIGPIPE信号,否则当客户端退出后,服务器仍然向该socket发送数据时,则会引起Crash;
SIGCHLD:僵尸进程是一个早已死亡的进程、但在进程表中仍占有位置;Linux中当子进程结束的时候,他并没有完全销毁,因为父进程还要用他的信息;父进程没有处理SIGCHLD信号且没有调用wait()/waitpid()等待子进程结束,就会出现僵尸进程;
2.1 发送信号
硬件方式:如:Ctrl + C 或者Ctrl + \
软件方式:kill API 如:kill -9 pid
2.2 安装信号
void signal(int sig, void(*func)(int));
1 #include <stdio.h> 2 #include <signal.h> 3 #include <unistd.h> 4 5 void sighandle(int sig) 6 { 7 printf("received signal:%d\n", sig); 8 } 9 10 int main(int argc, char* argv) 11 { 12 signal(SIGINT, sighandle); 13 signal(SIGQUIT, sighandle); 14 signal(SIGHUP, sighandle); 15 pause() 16 return 0; 17 }
# gcc -g -o sig sig.c
# ./sig >> sig.txt
# 1.Ctrl + C | Ctrl + \ | close terminal
int sigaction(int sig, const struct sigaction* act, struct sigaction* oact);
1 /** 2 3 struct sigaction { 4 void (*sa_handler)(int); // 处理函数 5 void (*sa_sigaction)(int, siginfo_t*, void*); // 处理函数 6 sigset_t sa_mask; // 掩码 7 int sa_flags; // 根据SA_SIGINFO标记选择sa_handler/sa_sigaction 8 sa_handler 9 void (*sa_restorer)(void); // 设置为NULL,一般不用 10 }; 11 12 */ 13 14 #include <stdio.h> 15 #include <signal.h> 16 #include <unistd.h> 17 18 void sighandler(int sig) 19 { 20 printf("received signal:%d\n", sig); 21 } 22 23 int main(int argc, char* argv[]) 24 { 25 struct sigaction act, oact; 26 act.sa_handler = sighandler; 27 sigfillset(&act.sa_mask); 28 act.sa_flags = 0; 29 sigaction(SIGINT, &act, &oact); 30 31 pause(); 32 return 0; 33 } 34 35 # gcc -g -o sig sig.c 36 # ./sig
3.后台服务
3.1 fork方式
a.fork一个子进程,父进程退出,子进程成为孤儿进程,被init进程接管;
b.调用setsid()建立新的进程会话;
c.将当前工作目录切换到根目录;
d.将标准输入/输出,出错重定向到/dev/null
1 #include <stdio.h> 2 #include <unistd.h> 3 #include <stdlib.h> 4 #include <fcntl.h> 5 6 void daemonize() 7 { 8 int fd; 9 pid_t pid; 10 11 if ((pid == fork()) < 0) { 12 printf("can't create sub process\n"); 13 } else { 14 // parent process 15 if (pid != 0) { 16 exit(0); 17 } 18 } 19 20 setsid(); 21 22 if (chdir("/") < 0) { 23 printf("can't change sub process dir"); 24 exit(-1); 25 } 26 27 fd = open("/dev/null", O_RDWR); 28 dup2(fd, STDIN_FILENO); 29 dup2(fd, STDOUT_FILENO); 30 dup2(fd, STDERR_FILENO); 31 } 32 33 int main(int argc, char* argv[]) 34 { 35 daemonize(); 36 while (1) { 37 sleep(1); 38 } 39 40 return 0; 41 }
# ps -ef | grep daemon
# kill -9 pid
3.2 调用系统daemon API
1 /** 2 #include <stdlib.h> 3 int daemon(int nochdir, int noclose); 4 */ 5 6 #include <stdio.h> 7 #include <unistd.h> 8 #include <stdlib.h> 9 10 int main(int argc, char* argv[]) 11 { 12 if (daemon(0, 0) == -1) { 13 printf("call daemon error"); 14 exit(-1); 15 } 16 17 while (1) { 18 sleep(1); 19 } 20 21 return 0; 22 }
# killall -9 testdaemo