最新消息:XAMPP默认安装之后是很不安全的,我们只需要点击左方菜单的 "安全"选项,按照向导操作即可完成安全设置。

一次socket activation的探索体验

XAMPP下载 admin 737浏览 0评论

 

 

 

 这几天在研究runc的实现过程, 注意到它使用了的go-systemd的socket activationpackage, 出于好奇心,于是一探究竟.

服务的并行启动
systemd是一套用来管理主机上各个Daemon运行的工具, 开发目标是提供更优秀的框架以表示系统服务间的依赖关系,并依此实现系统初始化时服务的并行启动.
上面提到的并行很有意思, 不相干的Daemon并行启动自然没有什么问题,但倘若Daemon B依赖于Daemon A,那么它就必须等到Daemon A完成启动后才能启动,这就变成了串行.如果避免这种串行呢? 这需要了解两个Daemon的依赖性的本质.通常来说,如果Daemon B依赖Daemon A,那么就说明Daemon B(Clinet)启动时会向Daemon A(Server)发起连接.由于Daemon A和Daemon B通常在一台主机上, 因此它们之间的C-S连接通常使用Unix Socket完成.

而socket activation的思想就是: Daemon B启动时其实并不需要Daemon A真正运行起来,它只需要Daemon A建立的socket处于listen状态就OK了. 而这个socket不必由Daemon A建立, 而是由systemd在系统初始化时就建立. 当Daemon B发起启动时发起连接,systemd再将Daemon A启动,
当Daemon A启动后,然后将socket归还给Daemon A. 这个过程如下图所示.

QQ截图20181125125744

 

 例子
Server端
vim server.c
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <sys/un.h>
#include <systemd/sd-daemon.h>

int main()
{
int listenfd, connfd;
char recvbuf[1024];
ssize_t n;

union {
struct sockaddr sa;
struct sockaddr_un un;
}sa;

if (sd_listen_fds(0)!=1) {
fprintf(stderr,”No or too many fd received\n”);
}

listenfd = SD_LISTEN_FDS_START + 0;

if ((connfd = accept(listenfd, (struct sockaddr*)NULL, NULL))<0) {
fprintf(stderr ,”accept(): %m\n”);
}

for (;;) {
if ((n = read(connfd, recvbuf, sizeof(recvbuf))) < 0) {
fprintf(stderr, “read()\n”);
}

recvbuf[n] = ”;
write(connfd, recvbuf, n);
}
close(connfd);
close(listenfd);
return 0;
}
其中sd_listen_fds将从systemd拿到处于listen状态的socket.

编译生成可执行文件, 并将其移动到/usr/bin/目录

gcc server.c -lsystemd -o foobard
mv foobard /usr/bin/
如果编译提示找不到libsystemd或者<systemd/sd-daemon.h>,请参考文末附录安装libsystemd

vim /lib/systemd/system/foobar.socket
指定systemd要创建的unix socket路径为/run/foobar.sk

[Socket]
ListenStream=/run/foobar.sk

[Install]
WantedBy=sockets.target
vim /lib/systemd/system/foobar.service
[Service]
ExecStart=/usr/bin/foobard
Clinet端
vim clinet.c
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <sys/un.h>

int main()
{
int fd;
char sendbuf[1024];
ssize_t n;

union {
struct sockaddr sa;
struct sockaddr_un un;
}sa;

fd = socket(AF_UNIX, SOCK_STREAM, 0);
if (fd < 0) {
fprintf(stderr,”socket():%m\n”);
exit(1);
}
memset(&sa, 0, sizeof(sa));
sa.un.sun_family = AF_UNIX;

strncpy(sa.un.sun_path, “/run/foobar.sk

“, sizeof(sa.un.sun_path));

if (connect(fd, (struct sockaddr*)&sa, sizeof(sa))<0){
fprintf(stderr, “connect()%m\n”);
exit(1);
}
printf(“connect success !\n”);
for (;;) {
fgets(sendbuf, 1024, stdin);
if ((n = write(fd, sendbuf, strlen(sendbuf)))<0){
exit(1);
}

if ((n = read(fd, sendbuf, sizeof(sendbuf))) < 0){
exit(1);
}
sendbuf[n] = ”;
printf(“%s\n”, sendbuf);
memset(sendbuf, 0, sizeof(sendbuf));
}

return 0;
}
运行
启动socket

# systemctl enable foobar.socket
# systemctl start foobar.socket
# ls /run/foobar.sk

/run/foobar.sk

启动client

# ./client
connect success !
abc
abc
使用ps命令可看到foobard已经启动

# ps -aux | grep foobar
root     19480  0.0  0.0  23148  1360 ?        Ss   09:36   0:00 /usr/bin/foobard
附录 systemd 安装
在官网上下载安装包,这里以最新的systemd-221为例,下载后解压缩

# xz -d systemd-221.tar.xz
# tar -xvf systemd-221.tar
进入systemd-221目录

# cd systemd-221
systemd-221#./configure
如果提示 configure: error: Your intltool is too old. You need intltool 0.40.0 or later.
更新intltool(我使用的是ubuntu 16.04,其他linux发行版可选择自己的安装方式或源码安装)

# apt-get install intltool
如果提示configure: error: * gperf not found,则

# apt-get install gerf
如果提示configure: error: * libmount support required but libraries not found,则

# apt-get install libmount-dev
当通过configure检查之后,编译安装systemd

# make
# make install

转载请注明:XAMPP中文组官网 » 一次socket activation的探索体验

您必须 登录 才能发表评论!