服务端编程基础

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
posted @ 2020-06-06 17:33  sp0917  阅读(218)  评论(0编辑  收藏  举报