SylixOS驱动中锁的使用

gewenbin
gewenbin
gewenbin
188
文章
15
评论
2020年12月26日18:48:30 评论 584

在驱动开发中,有时候配合app测试之后,使用ts等命令发现只能打印出头部信息,主体信息无法打印,如下:

SylixOS驱动中锁的使用

原因:驱动中锁使用不规范导致系统死锁。

驱动测试代码:

#define  __SYLIXOS_KERNEL
#include <SylixOS.h>
#include <module.h>

LW_DEV_HDR        __GdevHdr;
LW_OBJECT_HANDLE  ulSem;

static LONG __devOpen(PLW_DEV_HDR pdevhdrHdr,
                      PCHAR       pcName,
                      INT         iFlag,
                      INT         iMode)
{
    ulSem = API_SemaphoreBCreate("test_sem", LW_TRUE, LW_OPTION_OBJECT_GLOBAL, LW_NULL);

    return 0;
}

static INT __devClose(PLW_FD_ENTRY  pFdEntry)
{
    API_SemaphoreBPend(ulSem, LW_OPTION_WAIT_INFINITE);

    /*
     *  some code
     */

    API_SemaphoreBPost(ulSem);

    return 0;
}


static INT  __devIoctl (PLW_FD_ENTRY  pFdEntry, INT  iCmd, LONG lArg)
{
    API_SemaphoreBPend(ulSem, LW_OPTION_WAIT_INFINITE);

    /*
     *  some code
     */
    while(1);

    API_SemaphoreBPost(ulSem);

    return 0;
}

struct file_operations __GdevOps = {
    .fo_open  = __devOpen,
    .fo_close = __devClose,
    .fo_ioctl = __devIoctl
};

static INT  __devRegister(VOID)
{
    INT iDrvNum    = iosDrvInstallEx2(&__GdevOps, LW_DRV_TYPE_NEW_1);   /*  安装驱动程序                */

    return  (iosDevAddEx(&__GdevHdr, "/dev/testdev", iDrvNum, DT_CHR)); /*  创建设备                    */
}

static INT  __devUnregister(VOID)
{
    PLW_DEV_HDR pDev;

    pDev = &__GdevHdr;

    if (pDev) {
        iosDevDelete(pDev);                                             /*  卸载设备                    */
        return  (iosDrvRemove(pDev->DEVHDR_usDrvNum, 0));               /*  卸载驱动程序                */
    } else {
        return  (PX_ERROR);
    }
}

int module_init (void)
{
    __devRegister();

    return 0;
}

void module_exit (void)
{
    __devUnregister();
}

APP测试代码:

#include <stdio.h>

int main (int argc, char **argv)
{
    INT iFbFd;

    iFbFd = open("/dev/testdev", O_RDWR);
    if (iFbFd < 0) {
        fprintf(stderr, "open /dev/testdev failed.\n");
        return (-1);
    }

    ioctl(iFbFd, NULL, NULL);

    return  (0);
}

分析:

  • ioctl中使用信号量保护了一段资源,使用while(1)模拟当进程还在执行资源区代码时被用户CTRL+C终止
  • 进程的资源回收工作是由t_reclaim线程负责的
  • t_reclaim线程会通过vprocIoReclaim函数回收进程打开的文件,主体回收代码使用_G_ulVProcMutex互斥锁保护
  • 在回收由驱动创建的设备文件资源时,最终会调用到驱动里的close函数
  • close函数中的ulSem信号量在ioctl中被用户进程持有,所以t_reclaim线程此时被阻塞,但是注意!此时t_reclaim线程还持有_G_ulVProcMutex互斥锁!
  • 这时使用ts查看线程信息,会调用vprocGetPidByTcbdesc函数以获取进程 id,这个函数中同样使用_G_ulVProcMutex互斥锁保护获取过程,但是此时_G_ulVProcMutex互斥锁是被t_reclaim线程持有的,所以当前线程阻塞,不会再输出信息

建议:

通过此案例可以看出,资源回收不当的话,会给系统带来负面影响。所以在驱动和应用开发中要注意进程结束时,资源该如何正确的回收,比如上面的测试用例如果能保证在ioctl执行完后再结束进程,就不会有死锁产生了。

gewenbin
  • 本文由 发表于 2020年12月26日18:48:30
  • 转载请务必保留本文链接:http://www.databusworld.cn/9787.html
匿名

发表评论

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: