file descriptors
pipes
This commit is contained in:
		
							parent
							
								
									b61c2547b8
								
							
						
					
					
						commit
						c41f1de5d4
					
				
					 16 changed files with 424 additions and 39 deletions
				
			
		
							
								
								
									
										18
									
								
								Makefile
									
										
									
									
									
								
							
							
						
						
									
										18
									
								
								Makefile
									
										
									
									
									
								
							|  | @ -1,5 +1,5 @@ | |||
| OBJS = main.o console.o string.o kalloc.o proc.o trapasm.o trap.o vectors.o \
 | ||||
|        syscall.o ide.o picirq.o mp.o spinlock.o | ||||
|        syscall.o ide.o picirq.o mp.o spinlock.o fd.o pipe.o | ||||
| 
 | ||||
| CC = i386-jos-elf-gcc | ||||
| LD = i386-jos-elf-ld | ||||
|  | @ -20,22 +20,30 @@ bootblock : bootasm.S bootmain.c | |||
| 	$(OBJCOPY) -S -O binary bootblock.o bootblock | ||||
| 	./sign.pl bootblock | ||||
| 
 | ||||
| kernel : $(OBJS) bootother.S user1 | ||||
| kernel : $(OBJS) bootother.S user1 usertests | ||||
| 	$(CC) -nostdinc -I. -c bootother.S | ||||
| 	$(LD) -N -e start -Ttext 0x7000 -o bootother.out bootother.o | ||||
| 	$(OBJCOPY) -S -O binary bootother.out bootother | ||||
| 	$(OBJDUMP) -S bootother.o > bootother.asm | ||||
| 	$(LD) -Ttext 0x100000 -e main -o kernel $(OBJS) -b binary bootother user1 | ||||
| 	$(LD) -Ttext 0x100000 -e main -o kernel $(OBJS) -b binary bootother user1 usertests | ||||
| 	$(OBJDUMP) -S kernel > kernel.asm | ||||
| 
 | ||||
| vectors.S : vectors.pl | ||||
| 	perl vectors.pl > vectors.S | ||||
| 
 | ||||
| user1 : user1.c | ||||
| user1 : user1.c ulib.o | ||||
| 	$(CC) -nostdinc -I. -c user1.c | ||||
| 	$(LD) -N -e main -Ttext 0 -o user1 user1.o | ||||
| 	$(LD) -N -e main -Ttext 0 -o user1 user1.o ulib.o | ||||
| 	$(OBJDUMP) -S user1 > user1.asm | ||||
| 
 | ||||
| usertests : usertests.c ulib.o | ||||
| 	$(CC) -nostdinc -I. -c usertests.c | ||||
| 	$(LD) -N -e main -Ttext 0 -o usertests usertests.o ulib.o | ||||
| 	$(OBJDUMP) -S usertests > usertests.asm | ||||
| 
 | ||||
| ulib.o : ulib.c | ||||
| 	$(CC) -nostdinc -I. -c ulib.c | ||||
| 
 | ||||
| -include *.d | ||||
| 
 | ||||
| clean :  | ||||
|  |  | |||
							
								
								
									
										8
									
								
								Notes
									
										
									
									
									
								
							
							
						
						
									
										8
									
								
								Notes
									
										
									
									
									
								
							|  | @ -83,3 +83,11 @@ it's IRQ 0, but it comes at a weird and changing vector (e.g. 119) if | |||
| you don't initialize the PIC. why doesn't jos see this? if i | ||||
| initialize the PIC with IRQ_OFFSET 32, the interrupt arrives at vector | ||||
| 32. | ||||
| 
 | ||||
| test out-of-fd cases for creating pipe. | ||||
| test pipe circular buffer | ||||
| test pipe writer or reader closes while other active or waiting | ||||
| test exit vs fd reference counts | ||||
| test write of more than PIPESIZE | ||||
| test reader goes first vs writer goes first | ||||
| test streaming of a lot of data | ||||
|  |  | |||
							
								
								
									
										16
									
								
								defs.h
									
										
									
									
									
								
							
							
						
						
									
										16
									
								
								defs.h
									
										
									
									
									
								
							|  | @ -37,6 +37,7 @@ void pic_init(void); | |||
| void mp_init(void); | ||||
| int cpu(void); | ||||
| int mp_isbcpu(void); | ||||
| void lapic_init(int c); | ||||
| 
 | ||||
| // spinlock.c
 | ||||
| extern uint32_t kernel_lock; | ||||
|  | @ -46,3 +47,18 @@ void release_grant_spinlock(uint32_t* lock, int cpu); | |||
| 
 | ||||
| // main.c
 | ||||
| void load_icode(struct proc *p, uint8_t *binary, unsigned size); | ||||
| 
 | ||||
| // pipe.c
 | ||||
| struct pipe; | ||||
| struct fd; | ||||
| int pipe_alloc(struct fd **fd1, struct fd **fd2); | ||||
| void pipe_close(struct pipe *p, int writeable); | ||||
| int pipe_write(struct pipe *p, char *addr, int n); | ||||
| int pipe_read(struct pipe *p, char *addr, int n); | ||||
| 
 | ||||
| // fd.c
 | ||||
| int fd_ualloc(); | ||||
| struct fd * fd_alloc(); | ||||
| void fd_close(struct fd *); | ||||
| int fd_read(struct fd *fd, char *addr, int n); | ||||
| int fd_write(struct fd *fd, char *addr, int n); | ||||
|  |  | |||
							
								
								
									
										80
									
								
								fd.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										80
									
								
								fd.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,80 @@ | |||
| #include "types.h" | ||||
| #include "param.h" | ||||
| #include "x86.h" | ||||
| #include "mmu.h" | ||||
| #include "proc.h" | ||||
| #include "defs.h" | ||||
| #include "fd.h" | ||||
| 
 | ||||
| struct fd fds[NFD]; | ||||
| 
 | ||||
| /*
 | ||||
|  * allocate a file descriptor number for curproc. | ||||
|  */ | ||||
| int | ||||
| fd_ualloc() | ||||
| { | ||||
|   int fd; | ||||
|   struct proc *p = curproc[cpu()]; | ||||
|   for(fd = 0; fd < NOFILE; fd++) | ||||
|     if(p->fds[fd] == 0) | ||||
|       return fd; | ||||
|   return -1; | ||||
| } | ||||
| 
 | ||||
| struct fd * | ||||
| fd_alloc() | ||||
| { | ||||
|   int i; | ||||
| 
 | ||||
|   for(i = 0; i < NFD; i++){ | ||||
|     if(fds[i].type == FD_CLOSED){ | ||||
|       fds[i].type = FD_NONE; | ||||
|       fds[i].count = 1; | ||||
|       return fds + i; | ||||
|     } | ||||
|   } | ||||
|   return 0; | ||||
| } | ||||
| 
 | ||||
| void | ||||
| fd_close(struct fd *fd) | ||||
| { | ||||
|   if(fd->type == FD_CLOSED || fd->count <= 0) | ||||
|     panic("fd_close"); | ||||
|   fd->count -= 1; | ||||
|   if(fd->count == 0){ | ||||
|     if(fd->type == FD_PIPE) | ||||
|       pipe_close(fd->pipe, fd->writeable); | ||||
|     fd->type = FD_CLOSED; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * addr is a kernel address, pointing into some process's p->mem. | ||||
|  */ | ||||
| int | ||||
| fd_write(struct fd *fd, char *addr, int n) | ||||
| { | ||||
|   if(fd->writeable == 0) | ||||
|     return -1; | ||||
|   if(fd->type == FD_PIPE){ | ||||
|     return pipe_write(fd->pipe, addr, n); | ||||
|   } else { | ||||
|     panic("fd_write"); | ||||
|     return -1; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| int | ||||
| fd_read(struct fd *fd, char *addr, int n) | ||||
| { | ||||
|   if(fd->readable == 0) | ||||
|     return -1; | ||||
|   if(fd->type == FD_PIPE){ | ||||
|     return pipe_read(fd->pipe, addr, n); | ||||
|   } else { | ||||
|     panic("fd_read"); | ||||
|     return -1; | ||||
|   } | ||||
| } | ||||
							
								
								
									
										9
									
								
								fd.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								fd.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,9 @@ | |||
| struct fd { | ||||
|   enum { FD_CLOSED, FD_NONE, FD_PIPE } type; | ||||
|   int count; // reference count
 | ||||
|   char readable; | ||||
|   char writeable; | ||||
|   struct pipe *pipe; | ||||
| }; | ||||
| 
 | ||||
| extern struct fd fds[NFD]; | ||||
							
								
								
									
										8
									
								
								main.c
									
										
									
									
									
								
							
							
						
						
									
										8
									
								
								main.c
									
										
									
									
									
								
							|  | @ -11,8 +11,8 @@ | |||
| 
 | ||||
| extern char edata[], end[]; | ||||
| extern int acpu; | ||||
| extern char _binary_user1_start[]; | ||||
| extern char _binary_user1_size[]; | ||||
| extern char _binary_user1_start[], _binary_user1_size[]; | ||||
| extern char _binary_usertests_start[], _binary_usertests_size[]; | ||||
| 
 | ||||
| char buf[512]; | ||||
| 
 | ||||
|  | @ -25,7 +25,7 @@ main() | |||
|     cprintf("an application processor\n"); | ||||
|     release_spinlock(&kernel_lock); | ||||
|     acquire_spinlock(&kernel_lock); | ||||
|     idtinit(); | ||||
|     idtinit(); // CPU's idt
 | ||||
|     lapic_init(cpu()); | ||||
|     curproc[cpu()] = &proc[0]; // XXX
 | ||||
|     swtch(); | ||||
|  | @ -70,7 +70,7 @@ main() | |||
| 
 | ||||
| #if 1 | ||||
|   p = newproc(); | ||||
|   load_icode(p, _binary_user1_start, (unsigned) _binary_user1_size); | ||||
|   load_icode(p, _binary_usertests_start, (unsigned) _binary_usertests_size); | ||||
| #endif | ||||
| 
 | ||||
| #if 0 | ||||
|  |  | |||
							
								
								
									
										2
									
								
								param.h
									
										
									
									
									
								
							
							
						
						
									
										2
									
								
								param.h
									
										
									
									
									
								
							|  | @ -2,3 +2,5 @@ | |||
| #define PAGE 4096 | ||||
| #define KSTACKSIZE PAGE | ||||
| #define NCPU 8 | ||||
| #define NOFILE 16 // file descriptors per process
 | ||||
| #define NFD 100 // file descriptors per system
 | ||||
|  |  | |||
							
								
								
									
										100
									
								
								pipe.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										100
									
								
								pipe.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,100 @@ | |||
| #include "types.h" | ||||
| #include "param.h" | ||||
| #include "x86.h" | ||||
| #include "mmu.h" | ||||
| #include "proc.h" | ||||
| #include "defs.h" | ||||
| #include "fd.h" | ||||
| 
 | ||||
| #define PIPESIZE 512 | ||||
| 
 | ||||
| struct pipe { | ||||
|   int readopen; // read fd is still open
 | ||||
|   int writeopen; // write fd is still open
 | ||||
|   int writep; // next index to write
 | ||||
|   int readp;  // next index to read
 | ||||
|   char data[PIPESIZE]; | ||||
| }; | ||||
| 
 | ||||
| int | ||||
| pipe_alloc(struct fd **fd1, struct fd **fd2) | ||||
| { | ||||
|   *fd1 = *fd2 = 0; | ||||
|   struct pipe *p = 0; | ||||
| 
 | ||||
|   if((*fd1 = fd_alloc()) == 0) | ||||
|     goto oops; | ||||
|   if((*fd2 = fd_alloc()) == 0) | ||||
|     goto oops; | ||||
|   if((p = (struct pipe *) kalloc(PAGE)) == 0) | ||||
|     goto oops; | ||||
|   (*fd1)->type = FD_PIPE; | ||||
|   (*fd1)->readable = 1; | ||||
|   (*fd1)->writeable = 0; | ||||
|   (*fd1)->pipe = p; | ||||
|   (*fd2)->type = FD_PIPE; | ||||
|   (*fd2)->readable = 0; | ||||
|   (*fd2)->writeable = 1; | ||||
|   (*fd2)->pipe = p; | ||||
|   return 0; | ||||
|  oops: | ||||
|   if(p) | ||||
|     kfree((char *) p, PAGE); | ||||
|   if(*fd1){ | ||||
|     (*fd1)->type = FD_NONE; | ||||
|     fd_close(*fd1); | ||||
|   } | ||||
|   if(*fd2){ | ||||
|     (*fd2)->type = FD_NONE; | ||||
|     fd_close(*fd2); | ||||
|   } | ||||
|   return -1; | ||||
| } | ||||
| 
 | ||||
| void | ||||
| pipe_close(struct pipe *p, int writeable) | ||||
| { | ||||
|   if(writeable) | ||||
|     p->writeopen = 0; | ||||
|   else | ||||
|     p->readopen = 0; | ||||
|   if(p->readopen == 0 && p->writeopen == 0) | ||||
|     kfree((char *) p, PAGE); | ||||
| } | ||||
| 
 | ||||
| int | ||||
| pipe_write(struct pipe *p, char *addr, int n) | ||||
| { | ||||
|   int i; | ||||
| 
 | ||||
|   for(i = 0; i < n; i++){ | ||||
|     while(((p->writep + 1) % PIPESIZE) == p->readp){ | ||||
|       if(p->readopen == 0) | ||||
|         return -1; | ||||
|       sleep(&p->writep); | ||||
|     } | ||||
|     p->data[p->writep] = addr[i]; | ||||
|     p->writep = (p->writep + 1) % PIPESIZE; | ||||
|   } | ||||
|   return i; | ||||
| } | ||||
| 
 | ||||
| int | ||||
| pipe_read(struct pipe *p, char *addr, int n) | ||||
| { | ||||
|   int i; | ||||
| 
 | ||||
|   while(p->readp == p->writep){ | ||||
|     if(p->writeopen == 0) | ||||
|       return 0; | ||||
|     sleep(&p->readp); | ||||
|   } | ||||
| 
 | ||||
|   for(i = 0; i < n; i++){ | ||||
|     if(p->readp == p->writep) | ||||
|       break; | ||||
|     addr[i] = p->data[p->readp]; | ||||
|     p->readp = (p->readp + 1) % PIPESIZE; | ||||
|   } | ||||
|   return i; | ||||
| } | ||||
							
								
								
									
										9
									
								
								proc.c
									
										
									
									
									
								
							
							
						
						
									
										9
									
								
								proc.c
									
										
									
									
									
								
							|  | @ -2,6 +2,7 @@ | |||
| #include "mmu.h" | ||||
| #include "x86.h" | ||||
| #include "param.h" | ||||
| #include "fd.h" | ||||
| #include "proc.h" | ||||
| #include "defs.h" | ||||
| 
 | ||||
|  | @ -49,6 +50,7 @@ newproc() | |||
|   struct proc *np; | ||||
|   struct proc *op = curproc[cpu()]; | ||||
|   unsigned *sp; | ||||
|   int fd; | ||||
| 
 | ||||
|   for(np = &proc[1]; np < &proc[NPROC]; np++) | ||||
|     if(np->state == UNUSED) | ||||
|  | @ -80,6 +82,13 @@ newproc() | |||
|   np->esp = (unsigned) sp; | ||||
|   np->ebp = (unsigned) sp; | ||||
| 
 | ||||
|   // copy file descriptors
 | ||||
|   for(fd = 0; fd < NOFILE; fd++){ | ||||
|     np->fds[fd] = op->fds[fd]; | ||||
|     if(np->fds[fd]) | ||||
|       np->fds[fd]->count += 1; | ||||
|   } | ||||
| 
 | ||||
|   np->state = RUNNABLE; | ||||
| 
 | ||||
|   cprintf("newproc %x\n", np); | ||||
|  |  | |||
							
								
								
									
										1
									
								
								proc.h
									
										
									
									
									
								
							
							
						
						
									
										1
									
								
								proc.h
									
										
									
									
									
								
							|  | @ -24,6 +24,7 @@ struct proc{ | |||
|   int pid; | ||||
|   int ppid; | ||||
|   void *chan; // sleep
 | ||||
|   struct fd *fds[NOFILE]; | ||||
| 
 | ||||
|   struct Taskstate ts;  // only to give cpu address of kernel stack
 | ||||
|   struct Segdesc gdt[NSEGS]; | ||||
|  |  | |||
							
								
								
									
										93
									
								
								syscall.c
									
										
									
									
									
								
							
							
						
						
									
										93
									
								
								syscall.c
									
										
									
									
									
								
							|  | @ -42,6 +42,88 @@ fetcharg(int argno, int *ip) | |||
|   return fetchint(curproc[cpu()], esp + 8 + 4*argno, ip); | ||||
| } | ||||
| 
 | ||||
| int | ||||
| putint(struct proc *p, unsigned addr, int ip) | ||||
| { | ||||
|   if(addr > p->sz - 4) | ||||
|     return 0; | ||||
|   memcpy(p->mem + addr, &ip, 4); | ||||
|   return 1; | ||||
| } | ||||
| 
 | ||||
| int | ||||
| sys_pipe() | ||||
| { | ||||
|   struct fd *rfd = 0, *wfd = 0; | ||||
|   int f1 = -1, f2 = -1; | ||||
|   struct proc *p = curproc[cpu()]; | ||||
|   unsigned fdp; | ||||
| 
 | ||||
|   if(pipe_alloc(&rfd, &wfd) < 0) | ||||
|     goto oops; | ||||
|   if((f1 = fd_ualloc()) < 0) | ||||
|     goto oops; | ||||
|   p->fds[f1] = rfd; | ||||
|   if((f2 = fd_ualloc()) < 0) | ||||
|     goto oops; | ||||
|   p->fds[f2] = wfd; | ||||
|   if(fetcharg(0, &fdp) < 0) | ||||
|     goto oops; | ||||
|   if(putint(p, fdp, f1) < 0) | ||||
|     goto oops; | ||||
|   if(putint(p, fdp+4, f2) < 0) | ||||
|     goto oops; | ||||
|   return 0; | ||||
| 
 | ||||
|  oops: | ||||
|   cprintf("sys_pipe failed\n"); | ||||
|   if(rfd) | ||||
|     fd_close(rfd); | ||||
|   if(wfd) | ||||
|     fd_close(wfd); | ||||
|   if(f1 >= 0) | ||||
|     p->fds[f1] = 0; | ||||
|   if(f2 >= 0) | ||||
|     p->fds[f2] = 0; | ||||
|   return -1; | ||||
| } | ||||
| 
 | ||||
| int | ||||
| sys_write() | ||||
| { | ||||
|   int fd, n; | ||||
|   unsigned addr; | ||||
|   struct proc *p = curproc[cpu()]; | ||||
| 
 | ||||
|   if(fetcharg(0, &fd) < 0 || fetcharg(1, &addr) < 0 || fetcharg(2, &n) < 0) | ||||
|     return -1; | ||||
|   if(fd < 0 || fd >= NOFILE) | ||||
|     return -1; | ||||
|   if(p->fds[fd] == 0) | ||||
|     return -1; | ||||
|   if(addr + n > p->sz) | ||||
|     return -1; | ||||
|   return fd_write(p->fds[fd], p->mem + addr, n); | ||||
| } | ||||
| 
 | ||||
| int | ||||
| sys_read() | ||||
| { | ||||
|   int fd, n; | ||||
|   unsigned addr; | ||||
|   struct proc *p = curproc[cpu()]; | ||||
| 
 | ||||
|   if(fetcharg(0, &fd) < 0 || fetcharg(1, &addr) < 0 || fetcharg(2, &n) < 0) | ||||
|     return -1; | ||||
|   if(fd < 0 || fd >= NOFILE) | ||||
|     return -1; | ||||
|   if(p->fds[fd] == 0) | ||||
|     return -1; | ||||
|   if(addr + n > p->sz) | ||||
|     return -1; | ||||
|   return fd_read(p->fds[fd], p->mem + addr, n); | ||||
| } | ||||
| 
 | ||||
| int | ||||
| sys_fork() | ||||
| { | ||||
|  | @ -122,7 +204,7 @@ syscall() | |||
|   int num = cp->tf->tf_regs.reg_eax; | ||||
|   int ret = -1; | ||||
| 
 | ||||
|   cprintf("%x sys %d\n", cp, num); | ||||
|   //cprintf("%x sys %d\n", cp, num);
 | ||||
|   switch(num){ | ||||
|   case SYS_fork: | ||||
|     ret = sys_fork(); | ||||
|  | @ -136,6 +218,15 @@ syscall() | |||
|   case SYS_cons_putc: | ||||
|     ret = sys_cons_putc(); | ||||
|     break; | ||||
|   case SYS_pipe: | ||||
|     ret = sys_pipe(); | ||||
|     break; | ||||
|   case SYS_write: | ||||
|     ret = sys_write(); | ||||
|     break; | ||||
|   case SYS_read: | ||||
|     ret = sys_read(); | ||||
|     break; | ||||
|   default: | ||||
|     cprintf("unknown sys call %d\n", num); | ||||
|     // XXX fault
 | ||||
|  |  | |||
|  | @ -2,3 +2,6 @@ | |||
| #define SYS_exit 2 | ||||
| #define SYS_wait 3 | ||||
| #define SYS_cons_putc 4 | ||||
| #define SYS_pipe 5 | ||||
| #define SYS_write 6 | ||||
| #define SYS_read 7 | ||||
|  |  | |||
							
								
								
									
										4
									
								
								trap.c
									
										
									
									
									
								
							
							
						
						
									
										4
									
								
								trap.c
									
										
									
									
									
								
							|  | @ -37,14 +37,14 @@ trap(struct Trapframe *tf) | |||
| 
 | ||||
|   acquire_spinlock(&kernel_lock); // released in trapret in trapasm.S
 | ||||
| 
 | ||||
|   cprintf("trap %d eip %x:%x\n", tf->tf_trapno, tf->tf_cs, tf->tf_eip); | ||||
| 
 | ||||
|   if(v == T_SYSCALL){ | ||||
|     curproc[cpu()]->tf = tf; | ||||
|     syscall(); | ||||
|     return; | ||||
|   } | ||||
| 
 | ||||
|   cprintf("trap %d eip %x:%x\n", tf->tf_trapno, tf->tf_cs, tf->tf_eip); | ||||
| 
 | ||||
|   if(v == 32){ | ||||
|     // probably clock
 | ||||
|     return; | ||||
|  |  | |||
							
								
								
									
										44
									
								
								ulib.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								ulib.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,44 @@ | |||
| int | ||||
| fork() | ||||
| { | ||||
|   asm("mov $1, %eax"); | ||||
|   asm("int $48"); | ||||
| } | ||||
| 
 | ||||
| void | ||||
| cons_putc(int c) | ||||
| { | ||||
|   asm("mov $4, %eax"); | ||||
|   asm("int $48"); | ||||
| } | ||||
| 
 | ||||
| int | ||||
| puts(char *s) | ||||
| { | ||||
|   int i; | ||||
| 
 | ||||
|   for(i = 0; s[i]; i++) | ||||
|     cons_putc(s[i]); | ||||
|   return i; | ||||
| } | ||||
| 
 | ||||
| int | ||||
| pipe(int fds[]) | ||||
| { | ||||
|   asm("mov $5, %eax"); | ||||
|   asm("int $48"); | ||||
| } | ||||
| 
 | ||||
| int | ||||
| read(int fd, char *buf, int n) | ||||
| { | ||||
|   asm("mov $7, %eax"); | ||||
|   asm("int $48"); | ||||
| } | ||||
| 
 | ||||
| int | ||||
| write(int fd, char *buf, int n) | ||||
| { | ||||
|   asm("mov $6, %eax"); | ||||
|   asm("int $48"); | ||||
| } | ||||
							
								
								
									
										38
									
								
								user1.c
									
										
									
									
									
								
							
							
						
						
									
										38
									
								
								user1.c
									
										
									
									
									
								
							|  | @ -1,35 +1,19 @@ | |||
| int | ||||
| fork() | ||||
| { | ||||
|   asm("mov $1, %eax"); | ||||
|   asm("int $48"); | ||||
| } | ||||
| 
 | ||||
| void | ||||
| cons_putc(int c) | ||||
| { | ||||
|   asm("mov $4, %eax"); | ||||
|   asm("int $48"); | ||||
| } | ||||
| 
 | ||||
| int | ||||
| puts(char *s) | ||||
| { | ||||
|   int i; | ||||
| 
 | ||||
|   for(i = 0; s[i]; i++) | ||||
|     cons_putc(s[i]); | ||||
|   return i; | ||||
| } | ||||
| char buf[32]; | ||||
| 
 | ||||
| main() | ||||
| { | ||||
|   int pid; | ||||
|   int pid, fds[2], n; | ||||
| 
 | ||||
|   pipe(fds); | ||||
|   pid = fork(); | ||||
|   if(pid == 0){ | ||||
|     cons_putc('C'); | ||||
|   if(pid > 0){ | ||||
|     write(fds[1], "xyz", 4); | ||||
|     puts("w"); | ||||
|   } else { | ||||
|     cons_putc('P'); | ||||
|     n = read(fds[0], buf, sizeof(buf)); | ||||
|     puts("r: "); | ||||
|     puts(buf); | ||||
|     puts("\n"); | ||||
|   } | ||||
|   while(1) | ||||
|     ; | ||||
|  |  | |||
							
								
								
									
										30
									
								
								usertests.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								usertests.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,30 @@ | |||
| // simple fork and pipe read/write
 | ||||
| 
 | ||||
| char buf[32]; | ||||
| 
 | ||||
| void | ||||
| pipe1() | ||||
| { | ||||
|   int fds[2], pid; | ||||
| 
 | ||||
|   pipe(fds); | ||||
|   pid = pipe(); | ||||
|   if(pid == 0){ | ||||
|     write(fds[1], "xyz", 4); | ||||
|   } else { | ||||
|     read(fds[0], buf, sizeof(buf)); | ||||
|     if(buf[0] != 'x' || buf[1] != 'y'){ | ||||
|       puts("pipe1 oops\n"); | ||||
|       return; | ||||
|     } | ||||
|   } | ||||
|   puts("pipe1 ok\n"); | ||||
| } | ||||
| 
 | ||||
| main() | ||||
| { | ||||
|   pipe1(); | ||||
| 
 | ||||
|   while(1) | ||||
|     ; | ||||
| } | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 rtm
						rtm