Linux kernel 活页夹中的双链接列表任务列表为什么为空?如何打印?

Linux kernel 活页夹中的双链接列表任务列表为什么为空?如何打印?,linux-kernel,doubly-linked-list,android-binder,Linux Kernel,Doubly Linked List,Android Binder,基于此修改binder.c代码 我想打印双链接列表任务列表: static int binder_free_thread(struct binder_proc *proc, struct binder_thread *thread) { struct binder_transaction *t; struct binder_transaction *send_reply = NULL;

基于此修改binder.c代码

我想打印双链接列表任务列表:

static int binder_free_thread(struct binder_proc *proc,
                              struct binder_thread *thread)
{
        struct binder_transaction *t;
        struct binder_transaction *send_reply = NULL;
        int active_transactions = 0;
        static const size_t memberOffset = offsetof(binder_thread, wait);
        wait_queue_head_t *wqhptr = &thread->wait;
        struct list_head *n1,*p1;

        wait_queue_head_t *my2;


        printk(KERN_INFO "iovec str size:%d",sizeof(iovec));
        printk(KERN_INFO "thread->task_list:%p",(void *)&wqhptr->task_list);

        list_for_each_safe(p1,n1,  &wqhptr->task_list){
        my2 = list_entry(p1, wait_queue_head_t, task_list);
          printk (KERN_INFO "my2 t= %p %p" ,(void*)my2->task_list.prev,(void*)my2->task_list.next);
        }
它应该是列表的wait_队列头,所以我假设它应该包含条目。。。。但它什么也没显示

问题:

  • 如何填充它
  • 为什么它是空的
  • 仅供参考,指针&wqhptr->task_list指向一些内存

    代码触发:

            #include <fcntl.h>
            #include <sys/epoll.h>
            #include <sys/ioctl.h>
            #include <unistd.h>
    
            #define BINDER_THREAD_EXIT 0x40046208ul
    
            int main()
            {
                    int fd, epfd;
                    struct epoll_event event = { .events = EPOLLIN };
    
                    fd = open("/dev/binder0", O_RDONLY);
                    epfd = epoll_create(1000);
                    epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &event);
                    ioctl(fd, BINDER_THREAD_EXIT, NULL);
            }
    
    这个可以打印条目

    我认为线程->等待将与&pwq->等待相同。。。。。是吗

    问题:

  • 是还是不是
  • 如何从活页夹填充线程->等待,使其具有条目,并使其与&pwq->等待相对应,因为这是在空闲后使用的时候
  • 谢谢

    更新2:

    static void ep_remove_wait_queue(struct eppoll_entry *pwq)
    {
            wait_queue_head_t *whead;
            wait_queue_t *strptr;
            struct list_head *n1,*p1;
    
            wait_queue_t *my2;
    
    
            rcu_read_lock();
            /* If it is cleared by POLLFREE, it should be rcu-safe */
            whead = rcu_dereference(pwq->whead);
    
    
            if (whead)
            {
                    strptr=&pwq->wait;
    
    
                    list_for_each_safe(p1,n1,  &strptr->task_list){
                    my2 = list_entry(p1, wait_queue_t, task_list);
    
                    printk (KERN_INFO "my2= %p %p" ,(void*)my2->task_list.prev,(void*)my2->task_list.next);
                    }
    
    static void ep_remove_wait_queue(struct eppoll_entry *pwq)
    {
            wait_queue_head_t *whead;
            wait_queue_t *strptr;
            struct list_head *n1,*p1;
            wait_queue_t *my2;
    
    
            rcu_read_lock();
            /* If it is cleared by POLLFREE, it should be rcu-safe */
            whead = rcu_dereference(pwq->whead);
            printk(KERN_INFO "whead before");
    
            if (whead)
            {
                    strptr=&pwq->wait;
    
    
                    list_for_each_safe(p1,n1,  &pwq->whead){
                    my2 = list_entry(p1, wait_queue_t, task_list);
    
                    printk (KERN_INFO "my2= %p %p" ,(void*)my2->task_list.prev,(void*)my2->task_list.next);
                    }
    
    static void ep_remove_wait_queue(struct eppoll_entry *pwq)
    {
            wait_queue_head_t *whead;
            wait_queue_t *strptr;
            struct list_head *n1,*p1;
            wait_queue_t *my2;
    
    
            rcu_read_lock();
            /* If it is cleared by POLLFREE, it should be rcu-safe */
            whead = rcu_dereference(pwq->whead);
            printk(KERN_INFO "whead before");
    
            if (whead)
            {
                    strptr=&pwq->wait;
    
    
                    list_for_each_safe(p1,n1,  &pwq->whead->task_list){
                    my2 = list_entry(p1, wait_queue_t, task_list);
    
                    printk (KERN_INFO "my2= %p %p" ,(void*)my2->task_list.prev,(void*)my2->task_list.next);
                    }
    
    上面应该打印它吗

    谢谢

    更新3:

    static void ep_remove_wait_queue(struct eppoll_entry *pwq)
    {
            wait_queue_head_t *whead;
            wait_queue_t *strptr;
            struct list_head *n1,*p1;
    
            wait_queue_t *my2;
    
    
            rcu_read_lock();
            /* If it is cleared by POLLFREE, it should be rcu-safe */
            whead = rcu_dereference(pwq->whead);
    
    
            if (whead)
            {
                    strptr=&pwq->wait;
    
    
                    list_for_each_safe(p1,n1,  &strptr->task_list){
                    my2 = list_entry(p1, wait_queue_t, task_list);
    
                    printk (KERN_INFO "my2= %p %p" ,(void*)my2->task_list.prev,(void*)my2->task_list.next);
                    }
    
    static void ep_remove_wait_queue(struct eppoll_entry *pwq)
    {
            wait_queue_head_t *whead;
            wait_queue_t *strptr;
            struct list_head *n1,*p1;
            wait_queue_t *my2;
    
    
            rcu_read_lock();
            /* If it is cleared by POLLFREE, it should be rcu-safe */
            whead = rcu_dereference(pwq->whead);
            printk(KERN_INFO "whead before");
    
            if (whead)
            {
                    strptr=&pwq->wait;
    
    
                    list_for_each_safe(p1,n1,  &pwq->whead){
                    my2 = list_entry(p1, wait_queue_t, task_list);
    
                    printk (KERN_INFO "my2= %p %p" ,(void*)my2->task_list.prev,(void*)my2->task_list.next);
                    }
    
    static void ep_remove_wait_queue(struct eppoll_entry *pwq)
    {
            wait_queue_head_t *whead;
            wait_queue_t *strptr;
            struct list_head *n1,*p1;
            wait_queue_t *my2;
    
    
            rcu_read_lock();
            /* If it is cleared by POLLFREE, it should be rcu-safe */
            whead = rcu_dereference(pwq->whead);
            printk(KERN_INFO "whead before");
    
            if (whead)
            {
                    strptr=&pwq->wait;
    
    
                    list_for_each_safe(p1,n1,  &pwq->whead->task_list){
                    my2 = list_entry(p1, wait_queue_t, task_list);
    
                    printk (KERN_INFO "my2= %p %p" ,(void*)my2->task_list.prev,(void*)my2->task_list.next);
                    }
    
    尝试以上。。。重新编译

    更新4:

    static void ep_remove_wait_queue(struct eppoll_entry *pwq)
    {
            wait_queue_head_t *whead;
            wait_queue_t *strptr;
            struct list_head *n1,*p1;
    
            wait_queue_t *my2;
    
    
            rcu_read_lock();
            /* If it is cleared by POLLFREE, it should be rcu-safe */
            whead = rcu_dereference(pwq->whead);
    
    
            if (whead)
            {
                    strptr=&pwq->wait;
    
    
                    list_for_each_safe(p1,n1,  &strptr->task_list){
                    my2 = list_entry(p1, wait_queue_t, task_list);
    
                    printk (KERN_INFO "my2= %p %p" ,(void*)my2->task_list.prev,(void*)my2->task_list.next);
                    }
    
    static void ep_remove_wait_queue(struct eppoll_entry *pwq)
    {
            wait_queue_head_t *whead;
            wait_queue_t *strptr;
            struct list_head *n1,*p1;
            wait_queue_t *my2;
    
    
            rcu_read_lock();
            /* If it is cleared by POLLFREE, it should be rcu-safe */
            whead = rcu_dereference(pwq->whead);
            printk(KERN_INFO "whead before");
    
            if (whead)
            {
                    strptr=&pwq->wait;
    
    
                    list_for_each_safe(p1,n1,  &pwq->whead){
                    my2 = list_entry(p1, wait_queue_t, task_list);
    
                    printk (KERN_INFO "my2= %p %p" ,(void*)my2->task_list.prev,(void*)my2->task_list.next);
                    }
    
    static void ep_remove_wait_queue(struct eppoll_entry *pwq)
    {
            wait_queue_head_t *whead;
            wait_queue_t *strptr;
            struct list_head *n1,*p1;
            wait_queue_t *my2;
    
    
            rcu_read_lock();
            /* If it is cleared by POLLFREE, it should be rcu-safe */
            whead = rcu_dereference(pwq->whead);
            printk(KERN_INFO "whead before");
    
            if (whead)
            {
                    strptr=&pwq->wait;
    
    
                    list_for_each_safe(p1,n1,  &pwq->whead->task_list){
                    my2 = list_entry(p1, wait_queue_t, task_list);
    
                    printk (KERN_INFO "my2= %p %p" ,(void*)my2->task_list.prev,(void*)my2->task_list.next);
                    }
    
    活页夹c

    static int binder_free_thread(struct binder_proc *proc,
                                  struct binder_thread *thread)
    {
            struct binder_transaction *t;
            struct binder_transaction *send_reply = NULL;
            int active_transactions = 0;
            static const size_t memberOffset = offsetof(binder_thread, wait);
            wait_queue_head_t *wqhptr = &thread->wait;
            wait_queue_head_t *pwqhptr = &proc->wait;
            struct list_head *n1,*p1;
    
            wait_queue_t *my2;
    
    
            printk(KERN_INFO "iovec str size:%d",sizeof(iovec));
            printk(KERN_INFO "thread->task_list:%p",(void *)&wqhptr->task_list);
            printk(KERN_INFO "proc->task_list:%p",(void *)&pwqhptr->task_list);
            list_for_each_safe(p1,n1,  &pwqhptr->task_list){
              my2 = list_entry(p1, wait_queue_t, task_list);
              printk (KERN_INFO "p list= %p %p" ,(void*)my2->task_list.prev,(void*)my2->task_list.next);
            }
            list_for_each_safe(p1,n1,  &wqhptr->task_list){
              my2 = list_entry(p1, wait_queue_t, task_list);
              printk (KERN_INFO "t list= %p %p" ,(void*)my2->task_list.prev,(void*)my2->task_list.next);
            }
    
    eventpoll.c

    static void ep_remove_wait_queue(struct eppoll_entry *pwq)
    {
            wait_queue_head_t *whead;
            wait_queue_t *strptr;
            struct list_head *n1,*p1;
    
            wait_queue_t *my2;
    
    
            rcu_read_lock();
            /* If it is cleared by POLLFREE, it should be rcu-safe */
            whead = rcu_dereference(pwq->whead);
            printk(KERN_INFO "whead before");
    
            if (whead)
            {
                    strptr=&pwq->wait;
    
    
                    list_for_each_safe(p1,n1,  &pwq->whead->task_list){
                    my2 = list_entry(p1, wait_queue_t, task_list);
    
                    printk (KERN_INFO "my2= %p %p" ,(void*)my2->task_list.prev,(void*)my2->task_list.next);
                    }
    
    
                    remove_wait_queue(whead, &pwq->wait);
                    printk(KERN_INFO "remove wait queue:%p", (void*)&pwq->wait);
                    printk(KERN_INFO "remove wait queue task list:%p", (void*)&strptr->task_list);
    
    我看到列表已打印……但在Android启动期间,不是我的PoC:

    在Android启动期间

    [   84.747753] binder_ioctl: 1878:2371 40046208 0
    [   84.747765] iovec str size:8
    [   84.747771] thread->task_list:e4fb2e30
    [   84.747777] proc->task_list:e57d866c
    [   84.747784] p list= e57d866c e7fffe7c
    [   84.747790] p list= e656de7c e57d866c
    [   84.747797] binder_free_thread size:252 worker_off:44
    [   84.747804] freed thread:e4fb2e00
    
    我看到进程->任务列表。。。0xe4fb2e00的free()会影响它吗

    我的PoC:

    [  642.254192] wq queue:e7ce8798
    [  642.254201] epoll struct:e7ce8780
    [  642.254214] wq queue:e7ce8f98
    [  642.254220] epoll struct:e7ce8f80
    [  642.254230] wq queue:e7ce8718
    [  642.254236] epoll struct:e7ce8700
    [  642.254266] binder_ioctl: 7392:7392 40046208 0
    [  642.254274] iovec str size:8
    [  642.254280] thread->task_list:e5389b30
    [  642.254286] proc->task_list:c309d86c
    [  642.254292] binder_free_thread size:252 worker_off:44
    [  642.254299] freed thread:e5389b00
    [  642.254736] ep_unregister_pollwait struct:e7ce8780 epi struct:e51d0480
    [  642.254792] ep_unregister_pollwait struct:e7ce8f80 epi struct:e51d0a80
    [  642.254799] ep_unregister_pollwait list not empty
    [  642.254805] whead before
    [  642.254811] my2= c0f50cc4 c0f50cc4
    [  642.254817] remove wait queue:e734b994
    [  642.254823] remove wait queue task list:e734b9a0
    [  642.254830] ep_unregister_pollwait list not empty
    [  642.254835] whead before
    [  642.254841] my2= c0f50cd0 c0f50cd0
    [  642.254847] remove wait queue:e734bb24
    [  642.254852] remove wait queue task list:e734bb30
    [  642.254863] ep_free
    [  642.254873] ep_free
    [  642.254881] ep_free
    
    #include <fcntl.h>
    #include <sys/epoll.h>
    #include <sys/ioctl.h>
    #include <unistd.h>
    #include <stdio.h>
    
    
    #define BINDER_THREAD_EXIT 0x40046208ul
    #define BINDER_VERSION 0xc0046209ul
    
    int main()
    {
        int fd,fd1,fd2, epfd,epfd1,epfd2;
        struct epoll_event event = { .events = EPOLLOUT   };
    
        fd = open("/dev/binder", O_RDONLY);
        fd1 = open("/dev/random", O_RDONLY);
        epfd = epoll_create(1000);
        epfd1 = epoll_create(1000);
    
    
        if (epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &event)) err(1, "epoll_add");
        if (epoll_ctl(epfd1, EPOLL_CTL_ADD, fd1, &event)) err(1, "epoll_add");
    
    
    
    
        //ioctl(fd, BINDER_VERSION, NULL);
    
        ioctl(fd, BINDER_THREAD_EXIT, NULL);
        printf("Finished here.");
    }
    
    我的PoC:

    [  642.254192] wq queue:e7ce8798
    [  642.254201] epoll struct:e7ce8780
    [  642.254214] wq queue:e7ce8f98
    [  642.254220] epoll struct:e7ce8f80
    [  642.254230] wq queue:e7ce8718
    [  642.254236] epoll struct:e7ce8700
    [  642.254266] binder_ioctl: 7392:7392 40046208 0
    [  642.254274] iovec str size:8
    [  642.254280] thread->task_list:e5389b30
    [  642.254286] proc->task_list:c309d86c
    [  642.254292] binder_free_thread size:252 worker_off:44
    [  642.254299] freed thread:e5389b00
    [  642.254736] ep_unregister_pollwait struct:e7ce8780 epi struct:e51d0480
    [  642.254792] ep_unregister_pollwait struct:e7ce8f80 epi struct:e51d0a80
    [  642.254799] ep_unregister_pollwait list not empty
    [  642.254805] whead before
    [  642.254811] my2= c0f50cc4 c0f50cc4
    [  642.254817] remove wait queue:e734b994
    [  642.254823] remove wait queue task list:e734b9a0
    [  642.254830] ep_unregister_pollwait list not empty
    [  642.254835] whead before
    [  642.254841] my2= c0f50cd0 c0f50cd0
    [  642.254847] remove wait queue:e734bb24
    [  642.254852] remove wait queue task list:e734bb30
    [  642.254863] ep_free
    [  642.254873] ep_free
    [  642.254881] ep_free
    
    #include <fcntl.h>
    #include <sys/epoll.h>
    #include <sys/ioctl.h>
    #include <unistd.h>
    #include <stdio.h>
    
    
    #define BINDER_THREAD_EXIT 0x40046208ul
    #define BINDER_VERSION 0xc0046209ul
    
    int main()
    {
        int fd,fd1,fd2, epfd,epfd1,epfd2;
        struct epoll_event event = { .events = EPOLLOUT   };
    
        fd = open("/dev/binder", O_RDONLY);
        fd1 = open("/dev/random", O_RDONLY);
        epfd = epoll_create(1000);
        epfd1 = epoll_create(1000);
    
    
        if (epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &event)) err(1, "epoll_add");
        if (epoll_ctl(epfd1, EPOLL_CTL_ADD, fd1, &event)) err(1, "epoll_add");
    
    
    
    
        //ioctl(fd, BINDER_VERSION, NULL);
    
        ioctl(fd, BINDER_THREAD_EXIT, NULL);
        printf("Finished here.");
    }
    
    资料来源:

    我认为这里使用活页夹:

    https://github.com/LineageOS/android_packages_apps_LockClock/blob/5239d22272aa2b7a2bcf2c45482395da3e163289/src/org/lineageos/lockclock/DeviceStatusService.java
    

    你知道如何使用C(本机)代码复制吗?

    FYI指针&wqhptr->task\u列表指向一些内存。嗯,那只是
    任务列表
    member.hmm的地址,所以那里没有列表????奇怪的是,在ep_remove_wait_queue()中,eppoll_条目*pwq有一个带有任务列表的等待队列。。。。所以这与线程->等待不同?
    pwq->wait
    是一个
    wait\u queue\t
    但是
    thread->wait
    proc->wait
    wait\u queue\u head\t
    ,所以它们是不同的。但是,
    pwq->whead
    是指向
    等待队列头的指针
    binder\u poll()
    可以使用指向
    proc->wait
    thread->wait
    的指针调用
    poll\u wait()
    ,这样指针将位于
    pwq->whead
    ,而
    pwq->wait
    条目将在
    wait\u queue\u head\t
    上排队(使用
    struct list\u head task\u list
    成员)。关于“p list=”消息,也许您可以移动
    printk(内核信息“线程->任务列表:%p”,(void*)&wqhptr->任务列表)在打印线程任务列表的
    for
    循环之前调用。然后,您可以很容易地判断“p list=”消息是针对进程还是线程的。(或者,稍微更改其中一条“p list=”消息以区分它们。)对于您的调查,这是否有帮助?