2. 进程0是在系统初始化时由kernel自身从无到有创建.
3. 进程0的数据成员大部分是静态定义的,即由预先定义好的INIT_TASK, INIT_MM等宏初始化.进程0的描述符init_task定义在arch/arm/kernel/init_task.c,由INIT_TASK宏初始化。 i
nit_mm等结构体定义在include/linux/init_task.h内,为init_task成员的初始值,分别由对应的初始化宏如INIT_MM等初始化Process 1进程0最终会通过调用kernel_thread创建一个内核线程去执行init函数,这个新创建的内核线程即Process 1(这时还是共享着内核线程0的资源属性如地址空间等)。
init函数继续完成剩余的内核初始化,并在函数的最后调用execve系统调用装入用户空间的可执行程序/sbin/init,这时进程1就拥有了自己的属性资源,成为一个普通进程(init进程)。
至此,内核初始化和启动过程结束。下面就进入了用户空间的初始化,最后运行shell登陆界面。
(注:Init进程一直存活,因为它创建和监控在 *** 作系统外层执行的所有进程的活动。)
——————这段对进程0的描述引用自《Understanding The Linux Kernel - Third Edtion》
The ancestor of all processes, called process 0, the idle process, or, for historical reasons, the swapper process, is a kernel thread created from scratch during the initialization phase of Linux. This ancestor process uses the following statically allocated data structures (data structures for all other processes are dynamically allocated)
用于进程间通信,通信机制由 *** 作系统保证,比较稳定。
在linux中可以通过kill -l查看所有信号的类型。
kill -信号类型 进程ID
int kill(pid_t pid, int sig)
入参pid :
pid >0: 发送信号给指定的进程。
pid = 0: 发送信号给 与调用kill函数进程属于同一进程组的所有进程。
pid <0: 取|pid|发给对应进程组。
pid = -1:发送给进程有权限发送的系统中所有进程。
sig :信号类型。
返回值 :成功:0;失败:-1 (ID非法,信号非法,普通用户杀init进程等权级问题),设置errno
以OpenHarmony源码为例,应用ANR后,AbilityManagerService会通知应用dump堆栈信息,就是通过信号量做的。
头文件位置 :
include <signal.h>
函数解释 :
typedef void (*sighandler_t)(int)
sighandler_t signal(int signum, sighandler_t handler)
当接收到指定的信号signum时,就会跳转到参数handler指定的函数执行。其中handler的入参是信号值。
函数原型 :
signum参数指出要捕获的信号类型,act参数指定新的信号处理方式,oldact参数输出先前信号的处理方式(如果不为NULL的话)。
sigaction结构体
sa_handler 信号处理函数
sa_mask 在处理该信号时可以暂时将sa_mask 指定的信号集搁置
sa_flags 指定一组修改信号行为的标志。 它由以下零个或多个的按位或组成
SA_RESETHAND:当调用信号处理函数时,将信号的处理函数重置为缺省值SIG_DFL
SA_RESTART:如果信号中断了进程的某个系统调用,则系统自动启动该系统调用
SA_NODEFER :一般情况下, 当信号处理函数运行时,内核将阻塞该给定信号。但是如果设置了 SA_NODEFER标记, 那么在该信号处理函数运行时,内核将不会阻塞该信号
sa_restorer 是一个替代的信号处理程序,当设置SA_SIGINFO时才会用它。
相关函数
int sigemptyset( sigset_t *set)
sigemptyset()用来将参数set信号集初始化并清空。
执行成功则返回0,如果有错误则返回-1。
完整示例
你说的问题我也不太懂,不过我这有些代码可以给你参考下:建立一个新的进程forkdemo1.c:
/* forkdemo1.c
* shows how fork creates two processes, distinguishable
* by the different return values from fork()
*/
#include <stdio.h>
main()
{
int ret_from_fork, mypid
mypid = getpid() /* who am i? */
printf("Before: my pid is %d\n", mypid) /* tell the world */
ret_from_fork = fork()
sleep(1)
printf("After: my pid is %d, fork() said %d\n",
getpid(), ret_from_fork)
}
子进程创建进程frokdemo2.c:
/* forkdemo2.c - shows how child processes pick up at the return
* from fork() and can execute any code they like,
* even fork(). Predict number of lines of output.
*/
main()
{
printf("my pid is %d\n", getpid() )
fork()
fork()
fork()
printf("After, my pid is %d\n", getpid() )
}
分辨父进程和子进程forkdemo3.c:
/* forkdemo3.c - shows how the return value from fork()
*allows a process to determine whether
*it is a child or process
*/
#include <stdio.h>
main()
{
int fork_rv
printf("Before: my pid is %d\n", getpid())
fork_rv = fork() /* create new process */
if ( fork_rv == -1 ) /* check for error */
perror("fork")
else if ( fork_rv == 0 )
printf("I am the child. my pid=%d\n", getpid())
else
printf("I am the parent. my child is %d\n", fork_rv)
}
父进程等待子进程的退出waitdemo.c:
/* waitdemo.c - shows how parent pauses until child finishes
*/
#include <stdio.h>
#define DELAY 2
main()
{
int newpid
void child_code(), parent_code()
printf("before: mypid is %d\n", getpid())
if ( (newpid = fork()) == -1 )
perror("fork")
else if ( newpid == 0 )
child_code(DELAY)
else
parent_code(newpid)
}
/*
* new process takes a nap and then exits
*/
void child_code(int delay)
{
printf("child %d here. will sleep for %d seconds\n", getpid(), delay)
sleep(delay)
printf("child done. about to exit\n")
exit(17)
}
/*
* parent waits for child then prints a message
*/
void parent_code(int childpid)
{
int wait_rv /* return value from wait() */
wait_rv = wait(NULL)
printf("done waiting for %d. Wait returned: %d\n", childpid, wait_rv)
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)