2011-7-29 16:38:16
第一次的设备移除是怎么产生的?
init_udevd_socket
监听了一个unix域的socket
有这样一个主循环
while (!udev_exit) {
struct udevd_uevent_msg *msg;
int fdcount;
FD_ZERO(&readfds);
FD_SET(signal_pipe[READ_END], &readfds);
FD_SET(udevd_sock, &readfds);
FD_SET(uevent_netlink_sock, &readfds);
if (inotify_fd >= 0)
FD_SET(inotify_fd, &readfds);
fdcount = select(maxfd+1, &readfds, NULL, NULL, NULL);
if (fdcount < 0) {
if (errno != EINTR)
err("error in select: %s\n", strerror(errno));
continue;
}
/* get control message */
if (FD_ISSET(udevd_sock, &readfds))
get_ctrl_msg();
/* get netlink message */
if (FD_ISSET(uevent_netlink_sock, &readfds)) {
msg = get_netlink_msg();
if (msg)
msg_queue_insert(msg);
}
/* received a signal, clear our notification pipe */
if (FD_ISSET(signal_pipe[READ_END], &readfds)) {
char buf[256];
read(signal_pipe[READ_END], &buf, sizeof(buf));
}
/* rules directory inotify watch */
if ((inotify_fd >= 0) && FD_ISSET(inotify_fd, &readfds)) {
int nbytes;
/* discard all possible events, we can just reload the config */
if ((ioctl(inotify_fd, FIONREAD, &nbytes) == 0) && nbytes > 0) {
char *buf;
reload_config = 1;
buf = malloc(nbytes);
if (buf == NULL) {
err("error getting buffer for inotify, disable watching\n");
close(inotify_fd);
inotify_fd = -1;
}
read(inotify_fd, buf, nbytes);
free(buf);
}
}
/* rules changed, set by inotify or a HUP signal */
if (reload_config) {
reload_config = 0;
udev_rules_cleanup(&rules);
udev_rules_init(&rules, 1);
}
/* forked child has returned */
if (sigchilds_waiting) {
sigchilds_waiting = 0;
reap_sigchilds();
}
if (run_exec_q) {
run_exec_q = 0;
if (!stop_exec_q)
msg_queue_manager();
}
}
rc = 0;
static int init_uevent_netlink_sock(void)
{
struct sockaddr_nl snl;
const int buffersize = 16 * 1024 * 1024;
int retval;
memset(&snl, 0x00, sizeof(struct sockaddr_nl));
snl.nl_family = AF_NETLINK;
snl.nl_pid = getpid();
snl.nl_groups = 1;
uevent_netlink_sock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);
if (uevent_netlink_sock == -1) {
err("error getting socket: %s\n", strerror(errno));
return -1;
}
/* set receive buffersize */
setsockopt(uevent_netlink_sock, SOL_SOCKET, SO_RCVBUFFORCE, &buffersize, sizeof(buffersize));
retval = bind(uevent_netlink_sock, (struct sockaddr *) &snl, sizeof(struct sockaddr_nl));
if (retval < 0) {
err("bind failed: %s\n", strerror(errno));
close(uevent_netlink_sock);
uevent_netlink_sock = -1;
return -1;
}
return 0;
}
netlink 方便和内核进行沟通