继续 非标准的来自于 VxWorks 接口的实验
这下好了,文档断层了,有点令我头疼,继续。
下一个:task_init(struct tcb_s tcb, char *name, int priority, uint32_t *stack, uint32_t stack_size, maint_t entry, char const argv[])
下面有介绍,其中用粗体明确表示 not recommended 。看样子我可以偷个懒了。下一个:
task_activate(struct tcb_s *tcb)
在下面依旧可以看到:not recommended 。下一个:
task_activate(struct tcb_s *tcb)
依旧是 not recommended 。继续:
int task_delete(pid_t pid);
这个函数与 task_create() 成对出现。那么可以拿来测试。上次文档结束后,我测试了父进程和子进程都 printf ,结果是:可以看到两个进程相互在屏幕上打印字符。那么下面测试,在父子进程都打印 20 次的过程中,父进程在打印到10次的时候调用上面的函数。看看结果如何。首先,都打印20次时的输出:
(这里直接停止吧)测试后发现会出现错误。错误的缘由不明:nsh> hello_task 20
hello_task_main:task_create return:536871960hello_task_main:Hello World 1 times
hello_task_main:Hello World 2 times
hello_task_main:Hello World 3 times
hello_task_main:Hello World 4 times
hello_task_main:Hello World 5 times
hello_task_main:Hello World 6 times
hello_task_main:Hello World 7 times
print_hello:Hello World 1 times
hello_task_main:Hello World 8 times
print_hello:Hello World 2 times
hello_task_main:Hello World 9 times
print_hello:Hello World 3 times
hello_task_main:Hello World 10 times
print_hello:Hello World 4 times
hello_task_main:task_delete return:0
hello_task_main:Hello World 11 times
hello_task_main:Hello World 12 times
hello_task_main:Hello World 13 times
hello_task_up_hardfault: PANIC!!! Hard fault: 40000000
up_assert: Assertion failed at file:armv7-m/up_hardfault.c line: 171 taskt
up_dumpstate: sp: 10001718
up_dumpstate: stack base: 10000f78
up_dumpstate: stack size: 000007ec
up_dumpstate: ERROR: Stack pointer is not within the allocated stack
up_registerdump: R0: 00000001 10001610 10001608 0ffc0d9a 00000000 00000008
up_registerdump: R8: 00000000 00000000 00000000 00000000 00000000 100017f8
up_registerdump: xPSR: 81000000 PRIMASK: 00000001 CONTROL: 00000000再试试当子进程结束后再 delete。
还是一样报错。
看样子闲的没事干还是不要用这个函数了。。下一个:task_restart(pid_t pid)
在这里我发现一个奇怪的现象,输入2就可以运行,3就不行了。我开始怀疑是不是栈给的小了。去看一下,居然还是之前的768,我想768应该是小的可怜了。换成2048后可以运行3 和 4 但是不能运行 5。我觉得我可以肯定的是。之前出现错误一定是栈给的小了。但是出现的情况如下:子进程并不会因为 restart 重启。printf 再也没有执行。
标准接口实验
试验一下 exit() 的效果,发现并不好,连编译都不能过。看样子这个括号内还是要一个参数的。寻找一番,在 某个网站 上找到了参数 int code 的说明:
The value of status may be 0, EXIT_SUCCESS, EXIT_FAILURE,
原来是这样,参数填 EXIT_SUCCESS ,因为该宏定义就是 0。
在打印到一半时调用exit(EXIT_SUCCESS)
。测试结果是,父进程的输出直接没了。这也算是成功了吧。但是理论上说,父进程停止了,子进程为什么还能够继续输出呢?这里我怀疑这个我叫了很久的子进程是单独进程,并没有和我说的所谓的父进程构成父子关系。看样子之后的称呼就要改一改了。就用函数名来代替好了。下一个:getpid(void);
下一个就由两个进程同时输出自己的
pid
再各自的函数中加入printf("%s :pid = %d \n", argv[0], getpid());
输出结果:
nsh> hello_task
hello_task :pid = 2
print_hello :pid = 3
nsh> hello_task 1
hello_task :pid = 4
hello_task :Hello World 1 times
print_hello :pid = 5
print_hello :Hello World 1 times
print_hello :Hello World 2 times
nsh>看到这里突然有些不明白了,每个函数末尾的
return EXIT_SUCCESS
没有能使任务退出么?替换为上次的exit(EXIT_SUCCESS)
再次测试。相同的结果。这让我想到之前的task_delete()
再来试一下。意外的,之前出现的问题一个都没有了。
测试代码如下:#include <nuttx/config.h> #include <stdio.h> #include <stdlib.h> #include <errno.h> #define CONFIG_EXAMPLES_HELLO_TASK_PRIORITY SCHED_PRIORITY_DEFAULT #define CONFIG_EXAMPLES_HELLO_TASK_STACKSIZE 2048 int str2num(const char *s) { int rt = 0; while (*s >= '0' && *s <= '9') { rt = rt * 10 + (*s - '0'); s++; } return rt; } int print_hello(int argc, char *argv[]) { printf("%s: pid = %d \n", argv[0], getpid()); if (argv[1] != NULL) { auto int i; for (i = 0; i < 100; ++i) printf("%s: Hello World %d times \n", argv[0], i + 1); } exit(EXIT_SUCCESS); return EXIT_SUCCESS; } int hello_task_main(int argc, char *argv[]) { pid_t ret; ret = task_create("print_hello", CONFIG_EXAMPLES_HELLO_TASK_PRIORITY, CONFIG_EXAMPLES_HELLO_TASK_STACKSIZE, print_hello, &argv[1]); if (ret < 0) { int errcode = errno; printf("%s: ERROR: Failed to start print_hello: %d\n", argv[0], errcode); return EXIT_FAILURE; } else printf("%s: Started print_hello at PID=%d\n", argv[0], ret); if (argv[1] != NULL) { auto int i; auto int a; a = str2num(argv[1]); for (i = 0; i < a; ++i) printf("%s: Hello World %d times \n", argv[0], i + 1); } ret = task_delete(ret); printf("%s: Delete print_hello return:%d\n", argv[0], ret); exit(EXIT_SUCCESS); return EXIT_SUCCESS; }
print_hello
进程本来会打印100次,但是hello_task
会在自己打印完成时将print_hello
删除。测试结果:
nsh> hello_task 10
hello_task: Started print_hello at PID=5
hello_task: Hello World 1 times
hello_task: Hello World 2 times
hello_task: Hello World 3 times
hello_task: Hello World 4 times
hello_task: Hello World 5 times
hello_task: Hello World 6 times
hello_task: Hello World 7 times
print_hello: pid = 5
hello_task: Hello World 8 times
print_hello: Hello World 1 times
hello_task: Hello World 9 times
print_hello: Hello World 2 times
hello_task: Hello World 10 times
print_hello: Hello World 3 times
hello_task: Delete print_hello return:0
nsh>结果很理想。完全达到预期的效果。下一组
标准vfork和exec(v | l)接口
vfork
这里我查了很久,结果是这样的,调用这个函数,将会产生一个子进程。子进程和父进程拥有相同的代码,但是在调用后
vfork
在父子进程中的返回值不同。这个可能很难想象,待会用例子说明。execv
这个函数将直接调用 指定路径下的程序并给予参数。事实上,目前 NuttX 的路径下面什么都没有,
所以这个先跳过。在例程elf
中可以搜索到该字符串。所以这里试着开启一下例程elf
。。。。结果显而易见,出现大量错误。实在懒得看,先放着。execl
那就只演示一下
vfork
。
按照其返回两值,最简单的,用printf
输出其值,代码如下:#include <stdio.h> #include <stdlib.h> int hello_task_main(int argc, char *argv[]) { pid_t ret; if ((ret = vfork()) < 0) { int errcode = errno; printf("%s: ERROR: Failed to vfork hello_task_main: %d\n", argv[0], ret); return EXIT_FAILURE; } else if (ret == 0) { pid_t ch_proc = getpid(); printf("%s: im children process PID = %d\n", argv[0], ch_proc); exit(EXIT_SUCCESS); } else { pid_t fa_proc = getpid(); printf("%s: im father process PID = %d\n", argv[0], fa_proc); exit(EXIT_SUCCESS); } return EXIT_SUCCESS; }
实验结果:
nsh> hello_task
hello_task: im children process PID = 3
hello_task: im father process PID = 2
nsh>明显出现了两个进程,完成。下一组。
标准posix_spawn接口实验
在例程中,找到了
posix_spawn Unit Test
,开启这个例子。
打开后,出现了 ROMFS ,想了想,把这个打开好了。找一下,在这里:File Systems/ROMFS file system
开启它。
回到> Application Configuration > Examples
下,发现多了例子:ROMFS example
一并启用。
错误,那就慢慢来,先开启ROMFS example
。出现错误:Host executable genromfs not available in PATH
You may need todownload in from http://romfs.sourceforge.net/原来是少了东西。去NuttX官网看看
。。。
这里我要纠正一个之前的错误。是关于tools/README.txt
下第一段文档。当时这个没仔细看跳过了。但是万万没想到,我需要的ROMFS
就在这里。按照指示,git buildroot
:git clone https://bitbucket.org/nuttx/buildroot
注意路径,完成后
cd
进去。二话不说打开README
。
但是,我不得不说,这篇README
并没有什么帮助。按照安装Kconfig
的步骤,解压buildroot/toolchain/genromfs/
下的genromfs-0.5.2.tar.gz
进入make
make install
。然后再去编译NuttX。这回成功了。下载测试。
出错了,但是还算可以。我越来越怀疑是不是该按文档的顺序来学。
总之,这个测试失败了,目前有很多接口都卡在了文件系统上,因为目前文件系统没有可以运行的二进制文件。那只能继续前进了。
被这个搞得头疼。重开一篇。