6.3 Результаты выполнения работы
Текст программы forktest:
#include <unistd.h>
#include <stdio.h>
main(){
int i;
int pid=fork();
if (fork(); {
for (i=0;i<10;i++) printf ("I am a parent .. \n");
}else {
for (i=0;i<10;i++) printf ("I am a child! \n");
}
return 0;
}
Результаты выполнения forktest:
I am a child!
I am a child!
I am a child!
I am a child!
I am a child!
I am a child!
I am a child!
I am a child!
I am a child!
I am a child!
I am a parent ..
I am a parent ..
I am a parent ..
I am a parent ..
I am a parent ..
I am a parent ..
I am a parent ..
I am a parent ..
I am a parent ..
I am a parent ..
После выполнения fork() происходит раздвоение и появляется дочерний процесс.
после раздвоения первым активизируется родительский процесс;
в результате окончания текущего кванта времени, выделенного на выполнение родительского процесса, после перехода в системную фазу, родительский процесс приостанавливается;
дочерний процесс получает право на выполнение и в течении своего кванта времени
выполняется;
планировщик снова дает следующий квант времени родительскому процессу
Так продолжается до тех пор, пока процесс-родитель не закончит свою работу
2. Текст программы adrspace:
#include <stdio.h>
#include <unistd.h>
static int data1;
static unsigned long code, data, extend,stack;
main(int argc, char *argv[], char *envp[]){
int data2;
printf ("Addr of first evn. var. : %08x\n", envp[0]);
printf ("Addr of printf: %08x\n" ,printf);
printf ("Addr of main : %08x\n", main);
printf ("Addr of data1 : %08x\n", &data1);
printf ("Addr of data2 : %08x\n", &data2);
printf ("---------------------------------------------\n");
asm ("mov %cs, code");
asm ("mov %ds, data");
asm ("mov %es, extend");
asm ("mov %ss, stack");
printf (" CS: %04x\n", code);
printf (" DS: %04x\n", data);
printf (" ES: %04x\n", extend);
printf (" SS: %04x\n", stack);
return 0;
}
Результат выполнения:
Addr of first evn. var. : bfd6d728
Addr of printf: 08048320
Addr of main : 080483f4
Addr of data1 : 0804a020
Addr of data2 : bfd6d390
---------------------------------------------
CS: 0073
DS: 007b
ES: 007b
SS: 007b
Как видно, все сегментные регистры указывают не на реальные сегменты кода, данных и стека, а содержат смещение в глобальной таблице дескрипторов.
3. Текст модуля, содержащего процедуру procinfo:
#include <stdio.h>
#include <unistd.h>
#include <sys/resource.h>
#include <elf.h>
#include <sys/stat.h>
static unsigned long regESP;
extern char **environ;
int procinfo(void* r){
char *curr=(*environ)-2;
printf ("%s\n",curr);
char *currchar;
unsigned int argc_my;
char **argv_my;
int i,tmp;
int filecount=0;
char buf[255];
struct stat *buff;
FILE* iam;
unsigned int CODEbegin, CODEend, DATAbegin, DATAend,
STACKbegin, STACKend, ENVbegin, ENVend;
printf ("PID PPID UID GID SID PGID tty\n");
printf ("%-7d%-7d%-7d%-7d%-7d%-7d%s\n",getpid(),getppid(),
getuid(),getgid(),getsid(getpid()),getpgid(getpid()),ttyname(0));
for(i=65535;i>=0;i--)
if (!fstat(i,buff)) filecount++;
printf("Кол-во открытых файлов = %d\n",filecount);
getcwd(buf,255);
printf("Текущий каталог = %s\n",buf);
i=0;
while ((*curr)>30) { i++; curr--; }
printf("Приоритет = %d\n",getpriority(PRIO_PROCESS,0));
printf("Маска создания файлов = %03o\n",tmp=umask(0777)); umask(tmp);
if (iam=fopen(argv_my[0],"r"))
{
Elf32_Ehdr ELFhdr;
Elf32_Phdr PRGhdr;
int i;
fread(&ELFhdr,sizeof(Elf32_Ehdr),1,iam);
for (i=0;i<ELFhdr.e_phnum;i++)
{
fread(&PRGhdr,sizeof(Elf32_Phdr),1,iam);
if (PRGhdr.p_type==1)
{
/* Segment is executable & readable -> CODE*/
if (PRGhdr.p_flags==5)
{
CODEbegin=PRGhdr.p_vaddr;
CODEend=PRGhdr.p_vaddr+PRGhdr.p_memsz;
}
/* Segment is writable & readable -> DATA*/
if (PRGhdr.p_flags==6)
{
DATAbegin=PRGhdr.p_vaddr;
DATAend=PRGhdr.p_vaddr+PRGhdr.p_memsz;
}
}
}
fclose(iam);
}
while ((*curr++));
//STACKbegin=curr;
asm ("movl %ebp, regESP");
STACKend=regESP;
//ENVbegin=environ[0];
ENVend=0xC0000000;
/* Process virtual memory map: */
printf(" Код Данные Стек Среда\n");
printf("Start %-010p %-010p %-010p %-010p\n",
CODEbegin,DATAbegin,STACKbegin,ENVbegin);
printf("End %-010p %-010p %-010p %-010p\n",
CODEend,DATAend,STACKend,ENVend);
return 0;
}
Текст программы, вызывающей процедуру procinfo:
#include <pthread.h>
#include <sched.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <signal.h>
#include <sys/wait.h>
#include "procinfo.c"
extern int errno;
int procinfo(void* r);
static char child_stack[255];
int main()
{
int rez;
pthread_t * mythread;
procinfo(NULL);
if (fork())
{
printf("Ждем...\n");
wait(NULL);
printf("Дождались\n");
printf("Создаем поток для выполнения procinfo()...\n");
if ( (rez=clone(procinfo,child_stack,SIGCHLD,0)) >=0 )
{
printf("Поток был удачно создан, PID=%d! Waiting...",rez);
wait(NULL);
printf("Ok!\n");
}
else
{
switch (errno){
case EPERM : printf("EPERM\n"); break;
case ENOMEM: printf("ENOMEM\n"); break;
case EINVAL: printf("EINVAL\n"); break;
default : printf("DEFAULT!\n");
} }
}
else
{
printf("Я потомок. Вызываю procinfo()...\n");
procinfo(NULL);
}
return 0;
}
#include <pthread.h>
#include <sched.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <signal.h>
#include <sys/wait.h>
#include "procinfo.c"
extern int errno;
int procinfo(void* r);
static char child_stack[255];
int main()
{
int rez;
pthread_t * mythread;
procinfo(NULL);
if (fork())
{
printf("Ждем...\n");
wait(NULL);
printf("Дождались\n");
printf("Создаем поток для выполнения procinfo()...\n");
if ( (rez=clone(procinfo,child_stack,SIGCHLD,0)) >=0 )
{
printf("Поток был удачно создан, PID=%d! Waiting...",rez);
wait(NULL);
printf("Ok!\n");
}
else
{
switch (errno){
case EPERM : printf("EPERM\n"); break;
case ENOMEM: printf("ENOMEM\n"); break;
case EINVAL: printf("EINVAL\n"); break;
default : printf("DEFAULT!\n");
} }
}
else
{
printf("Я потомок. Вызываю procinfo()...\n");
procinfo(NULL);
}
return 0;
}
PID PPID UID GID SID PGID tty
6963 3956 1000 1000 3956 6963 /dev/pts/0
Текущий каталог = /media/Flash/lab_6/progs
Приоритет = 0
Маска создания файлов = 022
Код Данные Стек Среда
Start 0xb80a7b40 (nil) 0xb7f4241e 0xbf9cb0d8
End 0xb80c6948 0x8048486 0xbf9cb228 0xc0000000