[FS] Pipes
This commit is contained in:
parent
fd782365b7
commit
4bb9021885
23
init/init.c
23
init/init.c
@ -8,8 +8,27 @@ int main(int argc, char **argv)
|
|||||||
(void) argv;
|
(void) argv;
|
||||||
|
|
||||||
|
|
||||||
FILE *fp = fopen("/dev/debug", "w");
|
int fd[2];
|
||||||
fprintf(fp, "Hello, filesystem!\n");
|
pipe(fd);
|
||||||
|
|
||||||
|
pid_t childpid = fork();
|
||||||
|
|
||||||
|
if(childpid)
|
||||||
|
{
|
||||||
|
printf("I am parent!\n");
|
||||||
|
close(fd[1]);
|
||||||
|
write(fd[0], "Hi, pipe!\n", 10);
|
||||||
|
close(fd[0]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("I am child!\n");
|
||||||
|
close(fd[0]);
|
||||||
|
char buffer[255];
|
||||||
|
read(fd[1], buffer, 255);
|
||||||
|
printf("Received string: %s\n", buffer);
|
||||||
|
close(fd[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
for(;;);
|
for(;;);
|
||||||
|
150
kernel/fs/pipe.c
Normal file
150
kernel/fs/pipe.c
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
#include <vfs.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <sync.h>
|
||||||
|
#include <mem.h>
|
||||||
|
#include <debug.h>
|
||||||
|
#include <scheduler.h>
|
||||||
|
|
||||||
|
#define PIPE_SIZE 0x1000
|
||||||
|
|
||||||
|
struct pipe_data
|
||||||
|
{
|
||||||
|
uint8_t *buffer;
|
||||||
|
lock_t lock;
|
||||||
|
uint64_t size;
|
||||||
|
uint64_t readers;
|
||||||
|
uint64_t writers;
|
||||||
|
uint64_t read_pos;
|
||||||
|
uint64_t write_pos;
|
||||||
|
file_t *reader;
|
||||||
|
file_t *writer;
|
||||||
|
};
|
||||||
|
|
||||||
|
int pipe_open(file_t *file, uint64_t flags)
|
||||||
|
{
|
||||||
|
(void) flags;
|
||||||
|
struct pipe_data *d = file->data;
|
||||||
|
spin_lock(&d->lock);
|
||||||
|
if(file == d->reader)
|
||||||
|
d->readers ++;
|
||||||
|
else
|
||||||
|
d->writers ++;
|
||||||
|
spin_unlock(&d->lock);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pipe_close(file_t *file)
|
||||||
|
{
|
||||||
|
debug("Closing pipe\n");
|
||||||
|
struct pipe_data *d = file->data;
|
||||||
|
spin_lock(&d->lock);
|
||||||
|
if(file == d->reader)
|
||||||
|
d->readers --;
|
||||||
|
else
|
||||||
|
d->writers --;
|
||||||
|
if((!d->readers) && !(d->writers))
|
||||||
|
{
|
||||||
|
debug("Freeing pipe\n");
|
||||||
|
kfree(d);
|
||||||
|
kfree(file);
|
||||||
|
} else {
|
||||||
|
spin_unlock(&d->lock);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t pipe_read(file_t *file, void *buffer, size_t nbyte, size_t offset)
|
||||||
|
{
|
||||||
|
(void) offset;
|
||||||
|
struct pipe_data *d = file->data;
|
||||||
|
uint8_t *buf = buffer;
|
||||||
|
|
||||||
|
spin_lock(&d->lock);
|
||||||
|
while(d->read_pos >= d->write_pos)
|
||||||
|
{
|
||||||
|
spin_unlock(&d->lock);
|
||||||
|
schedule();
|
||||||
|
spin_lock(&d->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t bytes = d->write_pos - d->read_pos;
|
||||||
|
if(bytes > nbyte) bytes = nbyte;
|
||||||
|
|
||||||
|
uint64_t buf_pos = d->read_pos % d->size;
|
||||||
|
uint64_t n = d->size - buf_pos;
|
||||||
|
if(n > bytes) n = bytes;
|
||||||
|
|
||||||
|
memcpy(buf, &d->buffer[buf_pos], n);
|
||||||
|
if(bytes-n)
|
||||||
|
memcpy(&buf[n], d->buffer, bytes-n);
|
||||||
|
|
||||||
|
d->read_pos += bytes;
|
||||||
|
|
||||||
|
spin_unlock(&d->lock);
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t pipe_write(file_t *file, void *buffer, size_t nbyte, size_t offset)
|
||||||
|
{
|
||||||
|
(void) offset;
|
||||||
|
struct pipe_data *d = file->data;
|
||||||
|
uint8_t *buf = buffer;
|
||||||
|
uint64_t written = 0;
|
||||||
|
|
||||||
|
spin_lock(&d->lock);
|
||||||
|
while(nbyte)
|
||||||
|
{
|
||||||
|
while(d->write_pos >= d->read_pos + d->size)
|
||||||
|
{
|
||||||
|
spin_unlock(&d->lock);
|
||||||
|
schedule();
|
||||||
|
spin_lock(&d->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t bytes = d->size - (d->write_pos - d->read_pos);
|
||||||
|
if(bytes > nbyte) bytes = nbyte;
|
||||||
|
|
||||||
|
uint64_t buf_pos = d->write_pos % d->size;
|
||||||
|
uint64_t n = d->size - buf_pos;
|
||||||
|
if(n > bytes) n = bytes;
|
||||||
|
|
||||||
|
memcpy(&d->buffer[buf_pos], &buf[written], n);
|
||||||
|
if(bytes-n)
|
||||||
|
memcpy(d->buffer, &buf[written + n], bytes-n);
|
||||||
|
|
||||||
|
nbyte -= bytes;
|
||||||
|
d->write_pos += bytes;
|
||||||
|
written += bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
spin_unlock(&d->lock);
|
||||||
|
return written;
|
||||||
|
}
|
||||||
|
|
||||||
|
fs_driver_t pipe_writer = {
|
||||||
|
.open = pipe_open,
|
||||||
|
.close = pipe_close,
|
||||||
|
.write = pipe_write,
|
||||||
|
};
|
||||||
|
fs_driver_t pipe_reader = {
|
||||||
|
.open = pipe_open,
|
||||||
|
.close = pipe_close,
|
||||||
|
.read = pipe_read,
|
||||||
|
};
|
||||||
|
|
||||||
|
int pipe(file_t **r, file_t **w)
|
||||||
|
{
|
||||||
|
*r = kcalloc(1, sizeof(file_t));
|
||||||
|
*w = kcalloc(1, sizeof(file_t));
|
||||||
|
struct pipe_data *data = (*r)->data = (*w)->data = kcalloc(1, sizeof(struct pipe_data));
|
||||||
|
(*r)->driver = &pipe_reader;
|
||||||
|
(*w)->driver = &pipe_writer;
|
||||||
|
|
||||||
|
data->buffer = kcalloc(1, PIPE_SIZE);
|
||||||
|
data->size = PIPE_SIZE;
|
||||||
|
spin_unlock(&data->lock);
|
||||||
|
data->reader = *r;
|
||||||
|
data->writer = *w;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
@ -46,6 +46,7 @@ SYSCALL_DECL(read);
|
|||||||
SYSCALL_DECL(write);
|
SYSCALL_DECL(write);
|
||||||
SYSCALL_DECL(isatty);
|
SYSCALL_DECL(isatty);
|
||||||
SYSCALL_DECL(seek);
|
SYSCALL_DECL(seek);
|
||||||
|
SYSCALL_DECL(pipe);
|
||||||
|
|
||||||
SYSCALL_DECL(brk);
|
SYSCALL_DECL(brk);
|
||||||
|
|
||||||
|
@ -59,3 +59,4 @@ void fs_umount(const char *path);
|
|||||||
file_t *fs_namef(const char *path);
|
file_t *fs_namef(const char *path);
|
||||||
|
|
||||||
file_t debug_file;
|
file_t debug_file;
|
||||||
|
int pipe(file_t **reader, file_t **writer);
|
||||||
|
@ -78,3 +78,59 @@ SYSCALL_DEF(seek)
|
|||||||
|
|
||||||
return p->fp[fd].pos;
|
return p->fp[fd].pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SYSCALL_DEF(pipe)
|
||||||
|
{
|
||||||
|
SYSCALL_INIT(int *, fd);
|
||||||
|
process_t *p = get_current_process();
|
||||||
|
file_t *r, *w;
|
||||||
|
pipe(&r, &w);
|
||||||
|
|
||||||
|
fd[0] = -1;
|
||||||
|
fd[1] = -1;
|
||||||
|
|
||||||
|
int i;
|
||||||
|
for(i = 0; i < PROC_NUMFP; i++)
|
||||||
|
{
|
||||||
|
if(!p->fp[i].file)
|
||||||
|
{
|
||||||
|
p->fp[i].file = fs_get(w);
|
||||||
|
fs_open(w,0);
|
||||||
|
fd[0] = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(i == PROC_NUMFP)
|
||||||
|
goto pipe_fail;
|
||||||
|
for(i = 0; i < PROC_NUMFP; i++)
|
||||||
|
{
|
||||||
|
if(!p->fp[i].file)
|
||||||
|
{
|
||||||
|
p->fp[i].file = fs_get(r);
|
||||||
|
fs_open(r,0);
|
||||||
|
fd[1] = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(i == PROC_NUMFP)
|
||||||
|
goto pipe_fail;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
pipe_fail:
|
||||||
|
if(r)
|
||||||
|
kfree(r);
|
||||||
|
if(w)
|
||||||
|
kfree(w);
|
||||||
|
if(fd[0] != -1)
|
||||||
|
{
|
||||||
|
fs_put(p->fp[fd[0]].file);
|
||||||
|
p->fp[fd[0]].file = 0;
|
||||||
|
}
|
||||||
|
if(fd[1] != -1)
|
||||||
|
{
|
||||||
|
fs_put(p->fp[fd[1]].file);
|
||||||
|
p->fp[fd[1]].file = 0;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
@ -62,6 +62,7 @@ void syscall_init()
|
|||||||
SYSCALL_REGISTER(write, SYS_WRITE);
|
SYSCALL_REGISTER(write, SYS_WRITE);
|
||||||
SYSCALL_REGISTER(isatty, SYS_ISATTY);
|
SYSCALL_REGISTER(isatty, SYS_ISATTY);
|
||||||
SYSCALL_REGISTER(seek, SYS_SEEK);
|
SYSCALL_REGISTER(seek, SYS_SEEK);
|
||||||
|
SYSCALL_REGISTER(pipe, SYS_PIPE);
|
||||||
|
|
||||||
SYSCALL_REGISTER(brk, SYS_BRK);
|
SYSCALL_REGISTER(brk, SYS_BRK);
|
||||||
|
|
||||||
|
@ -69,3 +69,9 @@ SYSCALL_DEF(ioctl)
|
|||||||
kernel_debug("==> IOCTL - unsupported request:%lx\n", request);
|
kernel_debug("==> IOCTL - unsupported request:%lx\n", request);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SYSCALL_DEF(pipe)
|
||||||
|
{
|
||||||
|
SYSCALL_INIT(int *, fd);
|
||||||
|
return kernel_syscall(SYS_PIPE, fd);
|
||||||
|
}
|
||||||
|
@ -14,3 +14,5 @@
|
|||||||
#define SYS_FORK 0x008
|
#define SYS_FORK 0x008
|
||||||
#define SYS_EXIT 0x009
|
#define SYS_EXIT 0x009
|
||||||
#define SYS_WAIT 0x00A
|
#define SYS_WAIT 0x00A
|
||||||
|
|
||||||
|
#define SYS_PIPE 0x00B
|
||||||
|
Loading…
x
Reference in New Issue
Block a user