内核创建的用户进程printf不能输出一问的研究
转载:http://blog.chinaunix.net/uid-20543183-id-1930830.html
一:前言
二:fork()与execve()中stderr,stdio.stdout的继承关系
static int copy_files(unsigned long clone_flags, struct task_struct * tsk)
{
struct files_struct *oldf, *newf;
int error = 0;
oldf = current->files;
if (!oldf)
goto out;
if (clone_flags & CLONE_FILES) {
atomic_inc(&oldf->count);
goto out;
}
tsk->files = NULL;
newf = dup_fd(oldf, &error);
if (!newf)
goto out;
tsk->files = newf;
error = 0;
out:
return error;
}
static void flush_old_files(struct files_struct * files)
{
long j = -1;
struct fdtable *fdt;
spin_lock(&files->file_lock);
for (;;) {
unsigned long set, i;
j++;
i = j * __NFDBITS;
fdt = files_fdtable(files);
if (i >= fdt->max_fds)
break;
set = fdt->close_on_exec->fds_bits[j];
if (!set)
continue;
fdt->close_on_exec->fds_bits[j] = 0;
spin_unlock(&files->file_lock);
for ( ; set ; i++,set >>= 1) {
if (set & 1) {
sys_close(i);
}
}
spin_lock(&files->file_lock);
}
spin_unlock(&files->file_lock);
}
int get_unused_fd_flags(int flags)
{
……
…….
if (flags & O_CLOEXEC)
FD_SET(fd, fdt->close_on_exec);
else
FD_CLR(fd, fdt->close_on_exec);
……
}
三:用户空间的stderr,stdio.stdout初始化
#define INIT_TASK(tsk) \
{ .state = 0, .stack = &init_thread_info, .usage = ATOMIC_INIT(2), .flags = 0, .lock_depth = -1, .prio = MAX_PRIO-20, .static_prio = MAX_PRIO-20, .normal_prio = MAX_PRIO-20, .policy = SCHED_NORMAL, .cpus_allowed = CPU_MASK_ALL, …….
.files = &init_files, ……
}
它所有的文件描述符信息都是在init_files中的,定义如下:
static struct files_struct init_files = INIT_FILES;
#define INIT_FILES \
{ .count = ATOMIC_INIT(1), .fdt = &init_files.fdtab, .fdtab = INIT_FDTABLE, .file_lock = __SPIN_LOCK_UNLOCKED(init_task.file_lock), .next_fd = 0, .close_on_exec_init = { { 0, } }, .open_fds_init = { { 0, } }, .fd_array = { NULL, } }
static void noinline __init_refok rest_init(void)
__releases(kernel_lock)
{
int pid;
kernel_thread(kernel_init, NULL, CLONE_FS | CLONE_SIGHAND);
numa_default_policy();
pid = kernel_thread(kthreadd, NULL, CLONE_FS | CLONE_FILES);
kthreadd_task = find_task_by_pid(pid);
unlock_kernel();
/*
* The boot idle thread must execute schedule()
* at least once to get things moving:
*/
init_idle_bootup_task(current);
preempt_enable_no_resched();
schedule();
preempt_disable();
/* Call into cpu_idle with preempt disabled */
cpu_idle();
}
static int noinline init_post(void)
{
……
……
if (sys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0)
printk(KERN_WARNING "Warning: unable to open an initial console.\n");
(void) sys_dup(0);
(void) sys_dup(0);
……
……
run_init_process(XXXX);
}
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
main()
{
int ret;
char *ttyname0,*ttyname1,*ttyname2;
ttyname0 = ttyname(0);
ttyname1 = ttyname(1);
ttyname2 = ttyname(2);
printf(“file0 : %s\n”,ttyname0);
printf(“file1 : %s\n”,ttyname1);
printf(“file2 : %s\n”,ttyname2);
return;
}
四:内核创建用户空间进程的过程
#include <linux/ioport.h>
#include <linux/interrupt.h>
#include <asm/io.h>
#include <linux/serial_core.h>
#include <linux/kmod.h>
#include <linux/file.h>
#include <linux/unistd.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR( "ericxiao:[email protected]" );
static int exeuser_init()
{
int ret;
char *argv[] =
{
"/mnt/hgfs/vm_share/user_test/main",
NULL,
};
char *env[] =
{
"HOME=/",
"PATH=/sbin:/bin:/usr/sbin:/usr/bin",
NULL,
};
printk("exeuser_init ...\n");
ret = call_usermodehelper(argv[0], argv, env,UMH_WAIT_EXEC);
return 0;
}
static int exeuser_exit()
{
printk("exeuser_exit ...\n");
return 0;
}
module_init(exeuser_init);
module_exit(exeuser_exit);
用户空间程序代码:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(int argc,char *argv[],char *env[])
{
int i;
int fd;
int size;
char *tty;
FILE *confd;
char printfmt[4012];
system("echo i am coming > /var/console");
for(i=0; env[i]!=NULL;i++){
sprintf(printfmt,"echo env[%d]:%s. >>/var/console",i,env[i]);
system(printfmt);
}
for(i=0; i<argc ;i++){
sprintf(printfmt,"echo arg[%d]:%s. >>/var/console",i,argv[i]);
system(printfmt);
}
tty = ttyname(0);
if(tty == NULL)
system("echo tty0 is NULL >> /var/console");
else{
sprintf(printfmt,"echo ttyname0 %s. >>/var/console",tty);
system(printfmt);
}
tty = ttyname(1);
if(tty == NULL)
system("echo tty1 is NULL >> /var/console");
else{
sprintf(printfmt,"echo ttyname1 %s. >>/var/console",tty);
system(printfmt);
}
tty = ttyname(2);
if(tty == NULL)
system("echo tty2 is NULL >> /var/console");
else{
sprintf(printfmt,"echo ttyname2 %s. >>/var/console",tty);
system(printfmt);
}
tty = ttyname(fd);
if(tty == NULL)
system("echo fd is NULL >> /var/console");
else{
sprintf(printfmt,"echo fd %s. >>/var/console",tty);
system(printfmt);
}
return 0;
}
五:小结
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。