QNX驱动的入口从main开始,把每一个驱动看做一个进程模块。
int main(int argc, char *argv[])
spi_dev_t *head = NULL, *tail = NULL, *dev;
void *drventry, *dlhdl;
siginfo_t info;
sigset_t set;
int i, c, devnum = 0;
if (ThreadCtl(_NTO_TCTL_IO, 0) == -1) { /*获取IO控制权*/
perror("ThreadCtl");
return (!EOK);
}
/*初始化连接函数,通过 iofunc_func_init()函数初始化,通过连接和POSIX默认IO结构层功能。有关默认函数的信息,*/
_spi_init_iofunc();
/*获取 配置选项参数,通过build 相关命令可以配置SPI相关参数*/
while ((c = getopt(argc, argv, "u:d:")) != -1) {
switch (c) {
case 'u':
devnum = strtol(optarg, NULL, 0);
break;
case 'd':/*加载SPI驱动 以动态链接库方式加载 直接和底层相关*/
if ((drventry = _spi_dlload(&dlhdl, optarg)) == NULL) {
perror("spi_load_driver() failed");
return (-1);
}
do {
if ((dev = calloc(1, sizeof(spi_dev_t))) == NULL)
goto cleanup;
if (argv[optind] == NULL || *argv[optind] == '-')
dev->opts = NULL;
else
dev->opts = strdup(argv[optind]);
++optind;
dev->funcs = (spi_funcs_t *)drventry;/**/
dev->devnum = devnum++;
dev->dlhdl = dlhdl;
i = _spi_create_instance(dev);/*创建线程*/
if (i != EOK) {
perror("spi_create_instance() failed");
if (dev->opts)
free(dev->opts);
free(dev);
goto cleanup;
}
if (head) {
tail->next = dev;
tail = dev;
}
else
head = tail = dev;
} while (optind < argc && *(optarg = argv[optind]) != '-');
/*
* Now we only support one dll
*/
goto start_spi;
break;
}
}
start_spi:
if (head) {
/* background the process */
procmgr_daemon(0, PROCMGR_DAEMON_NOCLOSE | PROCMGR_DAEMON_NODEVNULL);
sigemptyset(&set);
sigaddset(&set, SIGTERM);
for (;;) {
if (SignalWaitinfo(&set, &info) == -1)
continue;
if (info.si_signo == SIGTERM)
break;
}
}
cleanup:
dev=head;
while (dev) {
if (dev->ctp) {
dispatch_unblock(dev->ctp);
}
if (dev->drvhdl) {
resmgr_detach(dev->dpp, dev->id, _RESMGR_DETACH_ALL);
dev->funcs->fini(dev->drvhdl);
}
if (dev->dpp) {
dispatch_destroy(dev->dpp);
}
head = dev->next;
if (dev->opts)
free(dev->opts);
free(dev);
dev=head;
}
dlclose(dlhdl);
return (EOK);
}