php两个进程监听同一个端口,多进程侦听同一端口

多进程侦听同一端口 多进程竞争连接请求

内核实现部分其实并不重要,也没什么好说的,只是比较好奇,就大致看一下相关实现。

1、等待队列头创建

最原始的等待队列在sock_alloc--->>>

static struct inode *sock_alloc_inode(struct super_block *sb)

{

init_waitqueue_head(&ei->socket.wait);

}

中实现,这里其实没有什么初始化,就是初始化了一个自旋锁,并且初始化为可获取状态,它并没有初始化方法成员。

然后在__sock_create--->>inet_create--->>>sock_init_data

sk->sk_sleep    =    &sock->wait;

这里将sk结构中的等待队列头指向socket中的wait成员,而这个sk_sleep将会是accept的等待队列头地址。

2、accept阻塞

sys_accept---->>>inet_accept--->>inet_csk_accept---->>>inet_csk_wait_for_connect--->>prepare_to_wait_exclusive(sk->sk_sleep, &wait,TASK_INTERRUPTIBLE)

wait->flags |= WQ_FLAG_EXCLUSIVE;

spin_lock_irqsave(&q->lock, flags);

if (list_empty(&wait->task_list))

__add_wait_queue_tail(q, wait);

/*

在加入等待队列之后,通过timeo = schedule_timeout(timeo);让出调度权。

这 里比较特殊的是这里的唤醒是互斥的,也就是那个 WQ_FLAG_EXCLUSIVE标志,这个标志会在唤醒函数中使用,当遇到这个标志并且唤醒互斥进程个数为1(默认情况)时只唤醒一个进程,其中的 prepare_to_wait_exclusiv的wait是通过下面宏创建的

DEFINE_WAIT(wait);

3、连接到来时唤醒

tcp_v4_do_rcv--->>>tcp_child_process

/* Wakeup parent, send SIGIO */

if (state == TCP_SYN_RECV && child->sk_state != state)

parent->sk_data_ready(parent, 0);

inet_create--->>>sock_init_data

sk->sk_state_change    =    sock_def_wakeup;

sk->sk_data_ready    =    sock_def_readable;

sk->sk_write_space    =    sock_def_write_space;

sk->sk_error_report    =    sock_def_error_report;

sk->sk_destruct        =    sock_def_destruct;

也就是执行的sk_data_ready即为sock_def_readable函数,在该函数中,其执行操作为

static void sock_def_readable(struct sock *sk, int len)

{

read_lock(&sk->sk_callback_lock);

if (sk->sk_sleep && waitqueue_active(sk->sk_sleep))

wake_up_interruptible(sk->sk_sleep);

sk_wake_async(sk,1,POLL_IN);

read_unlock(&sk->sk_callback_lock);

}

#define wake_up_interruptible(x)    __wake_up(x, TASK_INTERRUPTIBLE, 1, NULL)

可以看到,通过sk->sk_sleep唤醒了正在accept的接收套接口,并且其中__wake_up的唤醒互斥任务个数为1,所以只会唤醒一个进程,这次连接的到来对其它任务透明。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
当一台机器上出现两个Oracle数据库,且它们的监听器重合时,可能会导致以下问题。 首先,监听器是一种用于管理与数据库之间的通信的进程。它负责侦听来自客户端的连接请求,并将其转发给适当的数据库实例。当两个数据库的监听器重合时,可能会导致连接请求被错误地传递给错误的数据库实例,从而导致连接失败或错误的操作。 其次,监听器冲突可能会导致端口冲突。在一个机器上,每个监听器必须使用唯一的端口号来监听连接请求。如果两个监听器使用相同的端口号,将无法同时运行,从而导致其中一个监听器无法启动,影响数据库的正常运行。 解决这个问题的方法之一是修改其中一个数据库的监听器配置。可以通过修改监听器的配置文件(通常是listener.ora文件)来更改监听器的端口号和监听地址,确保它们不会与其他监听器发生冲突。修改后,重启监听器以使更改生效。 另外,还可以考虑使用多个网络适配器(NIC)来分离两个数据库的通信路径。通过将每个数据库连接到不同的NIC,可以确保它们在网络层次上具有不同的地址,并消除监听器之间的冲突。 总而言之,当一台机器上有两个Oracle数据库时,若它们的监听器重合,会导致连接问题和端口冲突等。解决方法包括修改监听器配置和使用多个网络适配器来分离通信路径。最重要的是确保每个监听器都有唯一的端口号和监听地址,以确保数据库的正常运行。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值