2009年5月12日火曜日

20090428のHomeWork

1. This week we have talked about processes. Write a program to call fork() repeatedly. Eventually, the call will fail in one of the children. When it does, print out the depth of the process tree: how many times have you succeeded in calling fork()? What was the reason for the failure (use perror())?

[実行結果]
fork error:: Resource temporarily unavailable
final i is 15986


2. Now modify that program to collect timing information for a given number of processes, giving the number of processes as an argument to the program (no argument should do the same as above, run until the fork fails). How long does it take to create and delete a thousand processes? Two thousand?

[1000の実行結果]
i is 1000
時間:0.154197931289672851562500000000

[2000の実行結果]
i is 2000
時間:0.278687000274658203125000000000


3.
a. Find the Linux kernel code for fork() and post it on your blog. If your machine is Linux, you may want to learn where the source code is stored on your machine (you may have to install it); if you are not using Linux, you may use one of the browsable Linux kernel source archives on the web (there are several; pick one).

[ソース]
long do_fork(unsigned long clone_flags,
unsigned long stack_start,
struct pt_regs *regs,
unsigned long stack_size,
int __user *parent_tidptr,
int __user *child_tidptr)
{
struct task_struct *p;
int trace = 0;
long nr;

if (unlikely(current->ptrace)) {
trace = fork_traceflag (clone_flags);
if (trace)
clone_flags |= CLONE_PTRACE;
}

p = copy_process(clone_flags, stack_start, regs, stack_size,
child_tidptr, NULL);
/*
* Do this prior waking up the new thread - the thread pointer
* might get invalid after that point, if the thread exits quickly.
*/
if (!IS_ERR(p)) {
struct completion vfork;

/*
* this is enough to call pid_nr_ns here, but this if
* improves optimisation of regular fork()
*/
nr = (clone_flags & CLONE_NEWPID) ?
task_pid_nr_ns(p, current->nsproxy->pid_ns) :
task_pid_vnr(p);
if (clone_flags & CLONE_PARENT_SETTID)
put_user(nr, parent_tidptr);

if (clone_flags & CLONE_VFORK) {
p->vfork_done = &vfork;
init_completion(&vfork);
}

if ((p->ptrace & PT_PTRACED) || (clone_flags & CLONE_STOPPED)) {
/*
* We'll start up with an immediate SIGSTOP.
*/
sigaddset(&p->pending.signal, SIGSTOP);
set_tsk_thread_flag(p, TIF_SIGPENDING);
}

if (!(clone_flags & CLONE_STOPPED))
wake_up_new_task(p, clone_flags);
else
p->state = TASK_STOPPED;

if (unlikely (trace)) {
current->ptrace_message = nr;
ptrace_notify ((trace << 8) | SIGTRAP);
}

if (clone_flags & CLONE_VFORK) {
freezer_do_not_count();
wait_for_completion(&vfork);
freezer_count();
if (unlikely (current->ptrace & PT_TRACE_VFORK_DONE)) {
current->ptrace_message = nr;
ptrace_notify ((PTRACE_EVENT_VFORK_DONE << 8) | SIGTRAP);
}
}
} else {
nr = PTR_ERR(p);
}
return nr;
}


b. Find the definition of the process or task structure from another operating system, either in a book or online. Post it on your blog. Over the next few weeks, we will compare this structure to Linux. You can find the definition for BSD, Windows, Symbian, NACHOS, Minix, or any other OS of your choice.

[FreeBSD 8-CURRENT]
/sys/proc.h

445 /*
446 * Process structure.
447 */
448 struct proc {
449 LIST_ENTRY(proc) p_list; /* (d) List of all processes. */
450 TAILQ_HEAD(, thread) p_threads; /* (c) all threads. */
451 struct mtx p_slock; /* process spin lock */
452 struct ucred *p_ucred; /* (c) Process owner's identity. */
453 struct filedesc *p_fd; /* (b) Open files. */
454 struct filedesc_to_leader *p_fdtol; /* (b) Tracking node */
455 struct pstats *p_stats; /* (b) Accounting/statistics (CPU). */
456 struct plimit *p_limit; /* (c) Process limits. */
457 struct callout p_limco; /* (c) Limit callout handle */
458 struct sigacts *p_sigacts; /* (x) Signal actions, state (CPU). */
459
460 /*
461 * The following don't make too much sense.
462 * See the td_ or ke_ versions of the same flags.
463 */
464 int p_flag; /* (c) P_* flags. */
465 enum {
466 PRS_NEW = 0, /* In creation */
467 PRS_NORMAL, /* threads can be run. */
468 PRS_ZOMBIE
469 } p_state; /* (j/c) S* process status. */
470 pid_t p_pid; /* (b) Process identifier. */
471 LIST_ENTRY(proc) p_hash; /* (d) Hash chain. */
472 LIST_ENTRY(proc) p_pglist; /* (g + e) List of processes in pgrp. */
473 struct proc *p_pptr; /* (c + e) Pointer to parent process. */
474 LIST_ENTRY(proc) p_sibling; /* (e) List of sibling processes. */
475 LIST_HEAD(, proc) p_children; /* (e) Pointer to list of children. */
476 struct mtx p_mtx; /* (n) Lock for this struct. */
477 struct ksiginfo *p_ksi; /* Locked by parent proc lock */
478 sigqueue_t p_sigqueue; /* (c) Sigs not delivered to a td. */
479 #define p_siglist p_sigqueue.sq_signals
480
481 /* The following fields are all zeroed upon creation in fork. */
482 #define p_startzero p_oppid
483 pid_t p_oppid; /* (c + e) Save ppid in ptrace. XXX */
484 struct vmspace *p_vmspace; /* (b) Address space. */
485 u_int p_swtick; /* (c) Tick when swapped in or out. */
486 struct itimerval p_realtimer; /* (c) Alarm timer. */
487 struct rusage p_ru; /* (a) Exit information. */
488 struct rusage_ext p_rux; /* (cj) Internal resource usage. */
489 struct rusage_ext p_crux; /* (c) Internal child resource usage. */
490 int p_profthreads; /* (c) Num threads in addupc_task. */
491 volatile int p_exitthreads; /* (j) Number of threads exiting */
492 int p_traceflag; /* (o) Kernel trace points. */
493 struct vnode *p_tracevp; /* (c + o) Trace to vnode. */
494 struct ucred *p_tracecred; /* (o) Credentials to trace with. */
495 struct vnode *p_textvp; /* (b) Vnode of executable. */
496 u_int p_lock; /* (c) Proclock (prevent swap) count. */
497 struct sigiolst p_sigiolst; /* (c) List of sigio sources. */
498 int p_sigparent; /* (c) Signal to parent on exit. */
499 int p_sig; /* (n) For core dump/debugger XXX. */
500 u_long p_code; /* (n) For core dump/debugger XXX. */
501 u_int p_stops; /* (c) Stop event bitmask. */
502 u_int p_stype; /* (c) Stop event type. */
503 char p_step; /* (c) Process is stopped. */
504 u_char p_pfsflags; /* (c) Procfs flags. */
505 struct nlminfo *p_nlminfo; /* (?) Only used by/for lockd. */
506 struct kaioinfo *p_aioinfo; /* (c) ASYNC I/O info. */
507 struct thread *p_singlethread;/* (c + j) If single threading this is it */
508 int p_suspcount; /* (j) Num threads in suspended mode. */
509 struct thread *p_xthread; /* (c) Trap thread */
510 int p_boundary_count;/* (c) Num threads at user boundary */
511 int p_pendingcnt; /* how many signals are pending */
512 struct itimers *p_itimers; /* (c) POSIX interval timers. */
513 /* End area that is zeroed on creation. */
514 #define p_endzero p_magic
515
516 /* The following fields are all copied upon creation in fork. */
517 #define p_startcopy p_endzero
518 u_int p_magic; /* (b) Magic number. */
519 int p_osrel; /* (x) osreldate for the
520 binary (from ELF note, if any) */
521 char p_comm[MAXCOMLEN + 1]; /* (b) Process name. */
522 struct pgrp *p_pgrp; /* (c + e) Pointer to process group. */
523 struct sysentvec *p_sysent; /* (b) Syscall dispatch info. */
524 struct pargs *p_args; /* (c) Process arguments. */
525 rlim_t p_cpulimit; /* (c) Current CPU limit in seconds. */
526 signed char p_nice; /* (c) Process "nice" value. */
527 int p_fibnum; /* in this routing domain XXX MRT */
528 /* End area that is copied on creation. */
529 #define p_endcopy p_xstat
530
531 u_short p_xstat; /* (c) Exit status; also stop sig. */
532 struct knlist p_klist; /* (c) Knotes attached to this proc. */
533 int p_numthreads; /* (c) Number of threads. */
534 struct mdproc p_md; /* Any machine-dependent fields. */
535 struct callout p_itcallout; /* (h + c) Interval timer callout. */
536 u_short p_acflag; /* (c) Accounting flags. */
537 struct proc *p_peers; /* (r) */
538 struct proc *p_leader; /* (b) */
539 void *p_emuldata; /* (c) Emulator state data. */
540 struct label *p_label; /* (*) Proc (not subject) MAC label. */
541 struct p_sched *p_sched; /* (*) Scheduler-specific data. */
542 STAILQ_HEAD(, ktr_request) p_ktr; /* (o) KTR event queue. */
543 LIST_HEAD(, mqueue_notifier) p_mqnotifier; /* (c) mqueue notifiers.*/
544 struct kdtrace_proc *p_dtrace; /* (*) DTrace-specific data. */
545 struct cv p_pwait; /* (*) wait cv for exit/exec */
546 };
547
548 #define p_session p_pgrp->pg_session
549 #define p_pgid p_pgrp->pg_id
550
551 #define NOCPU 0xff /* For when we aren't on a CPU. */
552
553 #define PROC_SLOCK(p) mtx_lock_spin(&(p)->p_slock)
554 #define PROC_SUNLOCK(p) mtx_unlock_spin(&(p)->p_slock)
555 #define PROC_SLOCK_ASSERT(p, type) mtx_assert(&(p)->p_slock, (type))

4. Determine how many processes have been created on your computer
since the last time it was booted. Describe any caveats on your knowledge.
26531

1 件のコメント:

  1. Looks like good work, but you didn't post the source code for your fork program!

    Score: 9/10

    返信削除