日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

linux 多个select,Linux select()和多个套接字的FIFO排序?

發布時間:2025/3/15 linux 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 linux 多个select,Linux select()和多个套接字的FIFO排序? 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

您可以使用IP_PKTINFO獲取數據包發送到的多播組的地址 - 即使套接字訂閱了一堆多播組。有了這個,您將按順序獲取數據包并按組地址過濾。請參閱以下示例:

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define PORT 1234

#define PPANIC(msg) perror(msg); exit(1);

#define STATS_PATCH 0

int main(int argc, char **argv)

{

fd_set master;

fd_set read_fds;

struct sockaddr_in serveraddr;

int sock;

int opt = 1;

size_t i;

int rc;

char *mcast_groups[] = {

"226.0.0.1",

"226.0.0.2",

NULL

};

#if STATS_PATCH

struct stat stat_buf;

#endif

struct ip_mreq imreq;

FD_ZERO(&master);

FD_ZERO(&read_fds);

rc = sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);

if(rc == -1)

{

PPANIC("socket() failed");

}

rc = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));

if(rc == -1)

{

PPANIC("setsockopt(reuse) failed");

}

memset(&serveraddr, 0, sizeof(serveraddr));

serveraddr.sin_family = AF_INET;

serveraddr.sin_port = htons(PORT);

serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);

rc = bind(sock, (struct sockaddr *)&serveraddr, sizeof(serveraddr));

if(rc == -1)

{

PPANIC("bind() failed");

}

rc = setsockopt(sock, IPPROTO_IP, IP_PKTINFO, &opt, sizeof(opt));

if(rc == -1)

{

PPANIC("setsockopt(IP_PKTINFO) failed");

}

for (i = 0; mcast_groups[i] != NULL; i++)

{

imreq.imr_multiaddr.s_addr = inet_addr(mcast_groups[i]);

imreq.imr_interface.s_addr = INADDR_ANY;

rc = setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (const void *)&imreq, sizeof(struct ip_mreq));

if (rc != 0)

{

PPANIC("joing mcast group failed");

}

}

FD_SET(sock, &master);

while(1)

{

read_fds = master;

rc = select(sock + 1, &read_fds, NULL, NULL, NULL);

if (rc == 0)

{

continue;

}

if(rc == -1)

{

PPANIC("select() failed");

}

if(FD_ISSET(sock, &read_fds))

{

char buf[1024];

int inb;

char ctrl_msg_buf[1024];

struct iovec iov[1];

iov[0].iov_base = buf;

iov[0].iov_len = 1024;

struct msghdr msg_hdr = {

.msg_iov = iov,

.msg_iovlen = 1,

.msg_name = NULL,

.msg_namelen = 0,

.msg_control = ctrl_msg_buf,

.msg_controllen = sizeof(ctrl_msg_buf),

};

struct cmsghdr *ctrl_msg_hdr;

inb = recvmsg(sock, &msg_hdr, 0);

if (inb < 0)

{

PPANIC("recvmsg() failed");

}

for (ctrl_msg_hdr = CMSG_FIRSTHDR(&msg_hdr); ctrl_msg_hdr != NULL; ctrl_msg_hdr = CMSG_NXTHDR(&msg_hdr, ctrl_msg_hdr))

{

if (ctrl_msg_hdr->cmsg_level == IPPROTO_IP && ctrl_msg_hdr->cmsg_type == IP_PKTINFO)

{

struct in_pktinfo *pckt_info = (struct in_pktinfo *)CMSG_DATA(ctrl_msg_hdr);

printf("got data for mcast group: %s\n", inet_ntoa(pckt_info->ipi_addr));

break;

}

}

printf("|");

for (i = 0; i < inb; i++)

printf("%c", isprint(buf[i])?buf[i]:'?');

printf("|\n");

#if STATS_PATCH

rc = fstat(sock, &stat_buf);

if (rc == -1)

{

perror("fstat() failed");

} else {

printf("st_atime: %d\n", stat_buf.st_atime);

printf("st_mtime: %d\n", stat_buf.st_mtime);

printf("st_ctime: %d\n", stat_buf.st_ctime);

}

#endif

}

}

return 0;

}下面的代碼不會解決OP問題,但可能會指導人們處理類似的要求

(編輯)一個人不應該在深夜做這樣的事情......即使有了這個解決方案,你也只能通過選擇獲得fd處理的訂單 - 而且這不會給你關于幀到達時間的指示。

如here所述,目前無法檢索套接字的順序或它們更改的時間戳,因為沒有為套接字inode設置所需的回調。但是,如果您能夠修補內核,則可以通過在select系統調用中設置時間來解決此問題。

以下補丁可能會給你一個想法:

diff --git a/fs/select.c b/fs/select.c

index 467bb1c..3f2927e 100644

--- a/fs/select.c

+++ b/fs/select.c

@@ -435,6 +435,9 @@ int do_select(int n, fd_set_bits *fds, struct timespec *end_time)

for (i = 0; i < n; ++rinp, ++routp, ++rexp) {

unsigned long in, out, ex, all_bits, bit = 1, mask, j;

unsigned long res_in = 0, res_out = 0, res_ex = 0;

+ struct timeval tv;

+

+ do_gettimeofday(&tv);

in = *inp++; out = *outp++; ex = *exp++;

all_bits = in | out | ex;

@@ -452,6 +455,16 @@ int do_select(int n, fd_set_bits *fds, struct timespec *end_time)

f = fdget(i);

if (f.file) {

const struct file_operations *f_op;

+ struct kstat stat;

+

+ int ret;

+ u8 is_sock = 0;

+

+ ret = vfs_getattr(&f.file->f_path, &stat);

+ if(ret == 0 && S_ISSOCK(stat.mode)) {

+ is_sock = 1;

+ }

+

f_op = f.file->f_op;

mask = DEFAULT_POLLMASK;

if (f_op->poll) {

@@ -464,16 +477,22 @@ int do_select(int n, fd_set_bits *fds, struct timespec *end_time)

res_in |= bit;

retval++;

wait->_qproc = NULL;

+ if(is_sock && f.file->f_inode)

+ f.file->f_inode->i_ctime.tv_sec = tv.tv_sec;

}

if ((mask & POLLOUT_SET) && (out & bit)) {

res_out |= bit;

retval++;

wait->_qproc = NULL;

+ if(is_sock && f.file->f_inode)

+ f.file->f_inode->i_ctime.tv_sec = tv.tv_sec;

}

if ((mask & POLLEX_SET) && (ex & bit)) {

res_ex |= bit;

retval++;

wait->_qproc = NULL;

+ if(is_sock && f.file->f_inode)

+ f.file->f_inode->i_ctime.tv_sec = tv.tv_sec;

}

/* got something, stop busy polling */

if (retval) {筆記:

這是......僅適合你:) - 不要指望它在主線

在測試每個相關的fd之前調用

do_gettimeofday()。

為了獲得更高的粒度,這應該在每次迭代中完成(并且僅在需要時)。因為stat-interface只提供一秒的粒度

你可以(!UGLY!)使用剩余的時間屬性將秒的分數映射到那些字段。

這是使用內核3.16.0完成的,并沒有經過充分測試。不要在太空船或醫療設備中使用它。如果您想嘗試一下,請獲取文件系統映像(例如https://people.debian.org/~aurel32/qemu/amd64/debian_wheezy_amd64_standard.qcow2)并使用qemu進行測試:

sudo qemu-system-x86_64 -kernel arch / x86 / boot / bzImage -hda debian_wheezy_amd64_standard.qcow2 -append“root = / dev / sda1”

總結

以上是生活随笔為你收集整理的linux 多个select,Linux select()和多个套接字的FIFO排序?的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。