AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / user-377749

bem22's questions

Martin Hope
bem22
Asked: 2020-02-12 14:53:31 +0800 CST

Linux ppp0 和默认路由以及如何访问公共互联网

  • 1

我的项目需要移动互联网。我试图通过使用带有 M2M sim(公共 IP,无 NAT)的 LTE 棒式调制解调器来实现这一点

这在 ubuntu (5.3.0-29-generic) 上运行良好,但我无法在 Raspbian Buster (4.19.97+) 上运行

Feb 11 22:31:48 raspberrypi systemd[1]: Reloading.
Feb 11 22:31:51 raspberrypi systemd[1]: [email protected]: Current command vanished from the unit file, execution of the command list won't be resumed.
Feb 11 22:31:51 raspberrypi systemd[1]: [email protected]: Current command vanished from the unit file, execution of the command list won't be resumed.
Feb 11 22:32:00 raspberrypi systemd[1]: Reloading.
Feb 11 22:32:41 raspberrypi pppd[699]: pppd 2.4.7 started by root, uid 0
Feb 11 22:32:41 raspberrypi pppd[699]: Using interface ppp0
Feb 11 22:32:41 raspberrypi pppd[699]: Connect: ppp0 <--> /dev/ttyUSB1
Feb 11 22:32:41 raspberrypi NetworkManager[288]: <info>  [1581460361.7138] manager: (ppp0): new Ppp device (/org/freedesktop/NetworkManager/Devices/5)
Feb 11 22:32:42 raspberrypi pppd[699]: CHAP authentication succeeded: Welcome!!
Feb 11 22:32:42 raspberrypi pppd[699]: CHAP authentication succeeded
Feb 11 22:32:42 raspberrypi pppd[699]: Could not determine remote IP address: defaulting to 10.64.64.64
Feb 11 22:32:42 raspberrypi pppd[699]: not replacing default route to eth0 [192.168.0.1]
Feb 11 22:32:42 raspberrypi pppd[699]: local  IP address 10.217.44.214
Feb 11 22:32:42 raspberrypi pppd[699]: remote IP address 10.64.64.64
Feb 11 22:32:42 raspberrypi pppd[699]: primary   DNS address 109.249.185.224
Feb 11 22:32:42 raspberrypi pppd[699]: secondary DNS address 109.249.186.32
Feb 11 22:32:42 raspberrypi NetworkManager[288]: <info>  [1581460362.2378] device (ppp0): state change: unmanaged -> unavailable (reason 'connection-assumed', sys-iface-state: 'external')
Feb 11 22:32:42 raspberrypi NetworkManager[288]: <info>  [1581460362.3090] device (ppp0): state change: unavailable -> disconnected (reason 'none', sys-iface-state: 'external')
Feb 11 22:35:30 raspberrypi pppd[699]: Terminating on signal 15
Feb 11 22:35:30 raspberrypi pppd[699]: Connect time 2.8 minutes.
Feb 11 22:35:30 raspberrypi pppd[699]: Sent 0 bytes, received 0 bytes.
Feb 11 22:35:30 raspberrypi NetworkManager[288]: <info>  [1581460530.4393] device (ppp0): state change: disconnected -> unmanaged (reason 'connection-assumed', sys-iface-state: 'external')
Feb 11 22:35:30 raspberrypi pppd[699]: Connection terminated.

为此,我尝试将 wvdial 与这些设置一起使用

[Dialer Defaults]
Auto DNS = yes
Init1 = ATZ+CFUN=1
Init2 = ATH
Init3 = ATE1
Init3 = AT+CGDCONT=1,"IP","EEM2M"
Stupid mode = 1
Baud = 9600
Dial Command = ATD
Modem = /dev/ttyUSB1
ISDN = 0
Phone = *99#
Password = bt
Username = bt

NetworkManager.conf 有这个内容

[main]
plugins=ifupdown,keyfile

[ifupdown]
managed=false

ppp/resolv.conf 有这个内容

nameserver 109.249.185.224
nameserver 109.249.186.32

我认为这是由设置设置的(请参阅上面的日志)

最后但并非最不重要的一点是,这表明我在 wvdial 运行后执行 ifconfig -a 时。请注意,ppp0 中的 6 个数据包是到 10.217.44.214 的内部 ping

eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.0.12  netmask 255.255.255.0  broadcast 192.168.0.255
        inet6 fe80::b435:fc5d:b267:a226  prefixlen 64  scopeid 0x20<link>
        ether 00:e0:92:00:15:f3  txqueuelen 1000  (Ethernet)
        RX packets 299  bytes 30739 (30.0 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 269  bytes 36598 (35.7 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 4  bytes 156 (156.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 4  bytes 156 (156.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

ppp0: flags=4305<UP,POINTOPOINT,RUNNING,NOARP,MULTICAST>  mtu 1500
        inet 10.217.44.214  netmask 255.255.255.255  destination 10.64.64.64
        ppp  txqueuelen 3  (Point-to-Point Protocol)
        RX packets 6  bytes 66 (66.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 7  bytes 129 (129.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

wwan0: flags=4098<BROADCAST,MULTICAST>  mtu 1500
        ether 00:1e:10:1f:00:00  txqueuelen 1000  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

编辑1:当以root身份运行wvdial时,我得到这个:

--> WvDial: Internet dialer version 1.61
--> Initializing modem.
--> Sending: ATZ+CFUN=1
OK
--> Sending: ATH
OK
--> Sending: AT+CGDCONT=1,"IP","EEM2M"
OK
--> Modem initialized.
--> Sending: ATD*99#
--> Waiting for carrier.
CONNECT 150000000
--> Carrier detected.  Starting PPP immediately.
--> Starting pppd at Tue Feb 11 23:01:49 2020
--> Pid of pppd: 1281
--> Using interface ppp0
--> pppd: X?C[01]X?C[01]
--> pppd: X?C[01]X?C[01]
--> pppd: X?C[01]X?C[01]
--> pppd: X?C[01]X?C[01]
--> pppd: X?C[01]X?C[01]
--> pppd: X?C[01]X?C[01]
--> local  IP address 10.217.44.214
--> pppd: X?C[01]X?C[01]
--> remote IP address 10.64.64.64
--> pppd: X?C[01]X?C[01]
--> primary   DNS address 109.249.185.224
--> pppd: X?C[01]X?C[01]
--> secondary DNS address 109.249.186.32
--> pppd: X?C[01]X?C[01]

我还注意到,当 wvdial 运行时,NetworkManager 将在 /etc/resolv.conf 中加载正确的 DNS,改变

# Generated by NetworkManager
nameserver 194.168.4.100
nameserver 194.168.8.100

至

nameserver 109.249.185.224
nameserver 109.249.186.32
# Generated by NetworkManager
raspberry-pi internet
  • 1 个回答
  • 3822 Views
Martin Hope
bem22
Asked: 2019-11-22 17:56:40 +0800 CST

内核空间内存释放冻结内核

  • 0

我正在编写一个内核模块。从用户空间读取字节并写回。

static ssize_t dev_read(struct file *filep, char *buffer, size_t len, loff_t *offset) {
    Node *msg;
    int error_count = 0;

    // Entering critical section
    down(&sem); //wait state

    msg = pop(&l, 0);

    // No message? No wait!
    if(!msg) {
        up(&sem);
        return -EAGAIN;
    }

    len = msg->length;
    error_count = copy_to_user(buffer, msg->string, msg->length);

    if (error_count == 0) {
        current_size -= msg->length;
        remove_element(&l, 0);
        up(&sem);
        return 0;
    } else {
        up(&sem);
        printk(KERN_INFO "opsysmem: Failed to send %d characters to the user\n", error_count);
        return -EFAULT; // Failed -- return a bad address message (i.e. -14)
    }
}

static ssize_t dev_write(struct file *filep, const char *buffer, size_t len, loff_t *offset) {
    Node *n;

    // buffer larger than 2 * 1024 bytes
    if(len > MAX_MESSAGE_SIZE || len == 0) {
        return -EINVAL;
    }

    n = kmalloc(sizeof(Node), GFP_KERNEL);

    if(!n) { 
        return -EAGAIN;
    }

    n->string = (char*) kmalloc(len, GFP_KERNEL);
    n->length = len;

    copy_from_user(n->string, buffer, len);

    // Enter critical section
    down(&sem); //wait state

    // buffer is larger than the total list memory (2MiB)
    if(current_size + len > MAX_LIST_SIZE) {
        up(&sem);
        return -EAGAIN;
    }

    current_size += len;

    push(&l, n);

    up(&sem);
    // Exit critical section

    return len;
}

销毁应该释放链表的函数

static void __exit opsysmem_exit(void) {
    // Deallocate the list of messages
    down(&sem);    
    destroy(&l);
    up(&sem);
    device_destroy(opsysmemClass, MKDEV(majorNumber, 0)); // remove the device

    class_unregister(opsysmemClass);                      // unregister the device class
    class_destroy(opsysmemClass);                         // remove the device class
    unregister_chrdev(majorNumber, DEVICE_NAME);          // unregister the major number
    printk(KERN_INFO "charDeviceDriver: Goodbye from the LKM!\n");
}

我的链表和销毁函数如下所示:

static void destroyNode(Node *n) {
    if(n) {
        destroyNode(n->next);
        kfree(n->string);
        n->string = NULL;
        kfree(n);
        n = NULL;
    }
}

static void destroy(list *l){
    if(l) {
        destroyNode(l->node);
    }
}
typedef struct Node {
    unsigned int length;
    char* string;
    struct Node *next;
} Node;

typedef struct list{
    struct Node *node;
} list;

问题如下:

我写入设备驱动程序,我想要rmmod驱动程序并且opsysmem_exit应该调用 kfree() 所有内存。

这在我有少量节点时有效。

如果我运行大量节点(1000+)并尝试使用 rmmode,虚拟机就会冻结。

你知道为什么以及我应该做些什么来诊断这个吗?

我的函数是否创建了太多级别的递归?

如果我写了 2000000 个节点然后我把它们读回来,似乎没有问题。就我 rmmod 时列表为空而言,一切正常。

编辑 1:我注意到如果我在不释放内存的情况下执行 rmmod,内核不会崩溃。但是,所有分配的内存都泄漏了,如kedr所示

linux-kernel kernel
  • 1 个回答
  • 295 Views
Martin Hope
bem22
Asked: 2019-11-21 16:32:58 +0800 CST

Linux 字符设备驱动程序问题

  • 0

我正在编写 LKM 来创建字符设备驱动程序。

Linux 内核:VirtualBox 中的 4.4.0-93-generic,2GB 内存,SWAP 为 300Kb

问题 1

如果我编写一个处理 dev_write 中的fd的 C 程序,一切都很好,它应该按原样读取,但是如果我尝试使用head -n 1 < /dev/opsysmem它不会输出任何内容。

从设备读取代码:

int main()
{
    int ret, fd;
    char stringToSend[BUFFER_LENGTH];
    printf("Starting device test code example...\n");
    fd = open("/dev/opsysmem", O_RDWR); // Open the device with read/write access
    if (fd < 0)
    {
        perror("Failed to open the device...");
        return errno;
    }

    printf("Press ENTER to read back from the device...\n");
    getchar();

    printf("Reading from the device...\n");
    ret = read(fd, receive, BUFFER_LENGTH); // Read the response from the LKM
    if (ret < 0)
    {
        perror("Failed to read the message from the device.");
        return errno;
    }
    printf("The received message is: [%s]\n", receive);

    return 0;
}

问题 2

如果我反复发送足够大的消息,一切都很好,我的 2MiB 缓冲区填满,然后丢弃以下消息。但是,如果消息更小(即每个 1 个字符),它会在大约 10000 个节点后停止。这是我的链表实现的问题,一个已知的 linux 问题,还是只是我没有观察到我的代码中的某些内容?

当我遇到问题 2 时,vCPU 以正弦方式节流

这是我的读写功能:

static ssize_t dev_read(struct file *filep, char *buffer, size_t len, loff_t *offset) {
    Node *msg;
    int ret_val;
    char* message;
    unsigned int message_length;

    // Entering critical section
    down(&sem); //wait state

    msg = pop(&l, 0);

    // No message? No wait!
    if(!msg) {
        up(&sem);
        return -EAGAIN;
    }

    if(len < msg->length) {
        up(&sem);
        return -EINVAL;
    }

    // Since we have a message, let's send it!
    current_size -= message_length;

    // copy_to_user has the format ( * to, *from, size) and returns 0 on success
    ret_val = copy_to_user(buffer, msg->string, message_length);

    if (!ret_val) {
        remove_element(&l, 0);
        up(&sem);
        return ret_val;
    } else {
        up(&sem);
        return -EFAULT; // Failed
    }
}


static ssize_t dev_write(struct file *filep, const char *buffer, size_t len, loff_t *offset) {
    Node *n;

    // buffer larger than 2 * 1024 bytes
    if(len > MAX_MESSAGE_SIZE || len == 0) {
        return -EINVAL;
    }

    n = kmalloc(sizeof(Node), GFP_KERNEL);

    if(!n) { 
        return -EAGAIN;
    }

    n->string = (char*) kmalloc(len, GFP_KERNEL);
    n->length = len;

    copy_from_user(n->string, buffer, len);

    // Enter critical section
    down(&sem); //wait state
    if(SLEEP) msleep(100);

    // buffer is larger than the total list memory (2MiB)
    if(current_size + len > MAX_LIST_SIZE) {
        up(&sem);
        return -EAGAIN;
    }

    current_size += len;

    push(&l, n);

    up(&sem);
    // Exit critical section

    return len;
}

这是我的链表及其功能

typedef struct Node {
    unsigned int length;
    char* string;
    struct Node *next;
} Node;

typedef struct list{
    struct Node *node;
} list;

static void init(list * l){
    l->node = NULL;
}

static void destroyNode(Node *n) {
    if(n) {
        destroyNode(n->next);
        kfree(n->string);
        n->string = NULL;
        kfree(n);
        n = NULL;
    }
}

static void destroy(list *l){
    if(l) {
        destroyNode(l->node);
    }
}

static Node* pop(list *l, unsigned int index) {
    struct Node *_current = l->node;

    // Cut down index until reaching the desired position
    while(_current) {
        if(index) {
            _current = _current->next;
            index--;
        } else { return _current; }
    }

    // If you are here, the node does not exist
    return NULL;
}

static int push(list * l, Node *n) {
    if(!n) { return -1; }

    // Initialize the string

    // Do we have a node in the list?
    if (l->node) { 
        // Virtually add it as a head
        n->next = l->node;
    } else {
        n->next = NULL;
    } // Otherwise prepare the list to have no tail

    // Now make the list point to the head
    l->node = n;

    return 0;
}

static int remove_element(list * l, unsigned int index){
    // Get the reference for head
    struct Node *previous;
    struct Node *_current;

    previous = NULL;
    _current = (Node*) l->node;

    // Swap _current until index
    while(_current) {
        // Is the index !0 and we have more nodes?
        if(index) {
            previous = _current;
            _current = _current->next;
            index--;
        } else {
            if(previous) {
                previous->next = _current->next;
            } else {
                l->node = _current->next;
            }
            // Free memory, assign NULL pointer
            kfree(_current->string);
            _current-> string = NULL;
            kfree(_current);
            _current = NULL;

            // Return success
            return 0;
        }
    }

    // No _current? No problem!
    return -1;
}

__ 问题 2 的更新 __ 我为输入字符串尝试了不同的大小,我发现:在对设备驱动程序进行大约 650 次调用后,大小为 3.3k,消息列表大小变为 4MiB(这是最大值)。对设备进行了几次调用,然后内核冻结。

编辑 1:我根据评论更新了 te dev_write 并删除了调试代码 编辑 2:添加了更多功能:push/pop/destroy 编辑 3:我检查了缓冲区长度与消息长度

linux ubuntu
  • 3 个回答
  • 848 Views
Martin Hope
bem22
Asked: 2019-11-20 02:17:15 +0800 CST

如何检测 linux 内核模块中的内存安全错误?

  • 1

在过去的一周里,我正在研究一个简单的内核模块,它创建了一个允许在用户和内核空间之间传递消息的字符设备驱动程序。

一切都很好,我找到了 KEDR ( https://github.com/euspectre/kedr ),现在我可以检测到内存泄漏。

但是,问题是:有没有办法检测越界访问和任何其他错误,例如未初始化的内存等?在用户空间程序中,我们有时可能会看到segfault,或者我们可以使用valgrind来尝试检测大多数这些错误。

我试图人为地写出数组的界限,操作系统没有抱怨。

linux
  • 1 个回答
  • 896 Views
Martin Hope
bem22
Asked: 2019-10-18 07:36:17 +0800 CST

两个文件描述符(客户端)之间的通信

  • 3

我正在关注这份文件

我很难理解文件描述符以及如何从一个文件描述符中读取数据、处理它然后发送到另一个文件描述符。

作为服务器,我需要能够接受连接、接收数据、处理数据,然后将其传递给另一个客户端。

昨天我被介绍了 epolling,我想知道我的策略对于创建客户端-服务器网络是否正确。

创建了一个 epollfd。我将其指定为边沿触发 (EPOLLET) 和非阻塞(使用:flags |= 0_NONBLOCK和 fctnl(epollfd, F_SETFL, flags).

我的意图是现在创建一个networkfds(客户端套接字)数组并监听连接/消息。

  1. 获取有关新数据的通知
  2. 读取数据
  3. 处理数据
  4. 将一些数据写入另一个套接字。

我在 linux man 和 online 中找到的所有示例仅提供有关如何从套接字读取数据的信息,如果我尝试让多个客户端实际上同时与多个客户端通信,我担心我的设计是愚蠢的并且由于失败。

我决定在这里问,因为我读到了 NGINX(网络服务器正在使用 epolling)

任何人都可以帮忙吗?

编辑1:我打算在列表(struct epoll_event *events)中有(许多)套接字并通过epoll_wait()访问它们。

// If I understand correctly: 
int ndfs = epoll_wait(epollfd, events, MAX_EVENTS, -1);
// Puts some events in the <events> array and an int in ndfs

nfdsevents现在应该包含可以使用 for 循环遍历的可用 fd 的数量。这就是我从手册中理解的。

一旦我收到其中一个消息,我希望能够处理它(即读取它的内容并做出决定)并最终触发对另一个套接字的写入。

我这样做是为了避免多线程。这是可以实现的吗?

linux
  • 3 个回答
  • 863 Views

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    模块 i915 可能缺少固件 /lib/firmware/i915/*

    • 3 个回答
  • Marko Smith

    无法获取 jessie backports 存储库

    • 4 个回答
  • Marko Smith

    如何将 GPG 私钥和公钥导出到文件

    • 4 个回答
  • Marko Smith

    我们如何运行存储在变量中的命令?

    • 5 个回答
  • Marko Smith

    如何配置 systemd-resolved 和 systemd-networkd 以使用本地 DNS 服务器来解析本地域和远程 DNS 服务器来解析远程域?

    • 3 个回答
  • Marko Smith

    dist-upgrade 后 Kali Linux 中的 apt-get update 错误 [重复]

    • 2 个回答
  • Marko Smith

    如何从 systemctl 服务日志中查看最新的 x 行

    • 5 个回答
  • Marko Smith

    Nano - 跳转到文件末尾

    • 8 个回答
  • Marko Smith

    grub 错误:你需要先加载内核

    • 4 个回答
  • Marko Smith

    如何下载软件包而不是使用 apt-get 命令安装它?

    • 7 个回答
  • Martin Hope
    user12345 无法获取 jessie backports 存储库 2019-03-27 04:39:28 +0800 CST
  • Martin Hope
    Carl 为什么大多数 systemd 示例都包含 WantedBy=multi-user.target? 2019-03-15 11:49:25 +0800 CST
  • Martin Hope
    rocky 如何将 GPG 私钥和公钥导出到文件 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Evan Carroll systemctl 状态显示:“状态:降级” 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim 我们如何运行存储在变量中的命令? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S 为什么 /dev/null 是一个文件?为什么它的功能不作为一个简单的程序来实现? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 如何从 systemctl 服务日志中查看最新的 x 行 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - 跳转到文件末尾 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla 为什么真假这么大? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis 在一个巨大的(70GB)、一行、文本文件中替换字符串 2017-12-30 06:58:33 +0800 CST

热门标签

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve