mirror of
https://github.com/SmallPond/MIT6.828_OS.git
synced 2026-05-01 06:09:45 +08:00
my solution to lab 6
This commit is contained in:
@@ -24,6 +24,10 @@ LIB_SRCFILES := $(LIB_SRCFILES) \
|
||||
lib/pageref.c \
|
||||
lib/spawn.c
|
||||
|
||||
LIB_SRCFILES := $(LIB_SRCFILES) \
|
||||
lib/sockets.c \
|
||||
lib/nsipc.c \
|
||||
lib/malloc.c
|
||||
LIB_SRCFILES := $(LIB_SRCFILES) \
|
||||
lib/pipe.c \
|
||||
lib/wait.c
|
||||
|
||||
@@ -126,6 +126,7 @@ fd_close(struct Fd *fd, bool must_exist)
|
||||
static struct Dev *devtab[] =
|
||||
{
|
||||
&devfile,
|
||||
&devsock,
|
||||
&devpipe,
|
||||
&devcons,
|
||||
0
|
||||
|
||||
@@ -141,6 +141,7 @@ devfile_write(struct Fd *fd, const void *buf, size_t n)
|
||||
// remember that write is always allowed to write *fewer*
|
||||
// bytes than requested.
|
||||
// LAB 5: Your code here
|
||||
|
||||
int r;
|
||||
if ( n > sizeof (fsipcbuf.write.req_buf))
|
||||
n = sizeof (fsipcbuf.write.req_buf);
|
||||
@@ -152,6 +153,7 @@ devfile_write(struct Fd *fd, const void *buf, size_t n)
|
||||
return fsipc(FSREQ_WRITE, NULL);
|
||||
|
||||
// panic("devfile_write not implemented");
|
||||
|
||||
}
|
||||
|
||||
static int
|
||||
|
||||
140
lab/lib/malloc.c
Normal file
140
lab/lib/malloc.c
Normal file
@@ -0,0 +1,140 @@
|
||||
|
||||
#include <inc/lib.h>
|
||||
|
||||
/*
|
||||
* Simple malloc/free.
|
||||
*
|
||||
* Uses the address space to do most of the hard work.
|
||||
* The address space from mbegin to mend is scanned
|
||||
* in order. Pages are allocated, used to fill successive
|
||||
* malloc requests, and then left alone. Free decrements
|
||||
* a ref count maintained in the page; the page is freed
|
||||
* when the ref count hits zero.
|
||||
*
|
||||
* If we need to allocate a large amount (more than a page)
|
||||
* we can't put a ref count at the end of each page,
|
||||
* so we mark the pte entry with the bit PTE_CONTINUED.
|
||||
*/
|
||||
enum
|
||||
{
|
||||
MAXMALLOC = 1024*1024 /* max size of one allocated chunk */
|
||||
};
|
||||
|
||||
#define PTE_CONTINUED 0x200
|
||||
|
||||
static uint8_t *mbegin = (uint8_t*) 0x08000000;
|
||||
static uint8_t *mend = (uint8_t*) 0x10000000;
|
||||
static uint8_t *mptr;
|
||||
|
||||
static int
|
||||
isfree(void *v, size_t n)
|
||||
{
|
||||
uintptr_t va, end_va = (uintptr_t) v + n;
|
||||
|
||||
for (va = (uintptr_t) v; va < end_va; va += PGSIZE)
|
||||
if (va >= (uintptr_t) mend
|
||||
|| ((uvpd[PDX(va)] & PTE_P) && (uvpt[PGNUM(va)] & PTE_P)))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void*
|
||||
malloc(size_t n)
|
||||
{
|
||||
int i, cont;
|
||||
int nwrap;
|
||||
uint32_t *ref;
|
||||
void *v;
|
||||
|
||||
if (mptr == 0)
|
||||
mptr = mbegin;
|
||||
|
||||
n = ROUNDUP(n, 4);
|
||||
|
||||
if (n >= MAXMALLOC)
|
||||
return 0;
|
||||
|
||||
if ((uintptr_t) mptr % PGSIZE){
|
||||
/*
|
||||
* we're in the middle of a partially
|
||||
* allocated page - can we add this chunk?
|
||||
* the +4 below is for the ref count.
|
||||
*/
|
||||
ref = (uint32_t*) (ROUNDUP(mptr, PGSIZE) - 4);
|
||||
if ((uintptr_t) mptr / PGSIZE == (uintptr_t) (mptr + n - 1 + 4) / PGSIZE) {
|
||||
(*ref)++;
|
||||
v = mptr;
|
||||
mptr += n;
|
||||
return v;
|
||||
}
|
||||
/*
|
||||
* stop working on this page and move on.
|
||||
*/
|
||||
free(mptr); /* drop reference to this page */
|
||||
mptr = ROUNDDOWN(mptr + PGSIZE, PGSIZE);
|
||||
}
|
||||
|
||||
/*
|
||||
* now we need to find some address space for this chunk.
|
||||
* if it's less than a page we leave it open for allocation.
|
||||
* runs of more than a page can't have ref counts so we
|
||||
* flag the PTE entries instead.
|
||||
*/
|
||||
nwrap = 0;
|
||||
while (1) {
|
||||
if (isfree(mptr, n + 4))
|
||||
break;
|
||||
mptr += PGSIZE;
|
||||
if (mptr == mend) {
|
||||
mptr = mbegin;
|
||||
if (++nwrap == 2)
|
||||
return 0; /* out of address space */
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* allocate at mptr - the +4 makes sure we allocate a ref count.
|
||||
*/
|
||||
for (i = 0; i < n + 4; i += PGSIZE){
|
||||
cont = (i + PGSIZE < n + 4) ? PTE_CONTINUED : 0;
|
||||
if (sys_page_alloc(0, mptr + i, PTE_P|PTE_U|PTE_W|cont) < 0){
|
||||
for (; i >= 0; i -= PGSIZE)
|
||||
sys_page_unmap(0, mptr + i);
|
||||
return 0; /* out of physical memory */
|
||||
}
|
||||
}
|
||||
|
||||
ref = (uint32_t*) (mptr + i - 4);
|
||||
*ref = 2; /* reference for mptr, reference for returned block */
|
||||
v = mptr;
|
||||
mptr += n;
|
||||
return v;
|
||||
}
|
||||
|
||||
void
|
||||
free(void *v)
|
||||
{
|
||||
uint8_t *c;
|
||||
uint32_t *ref;
|
||||
|
||||
if (v == 0)
|
||||
return;
|
||||
assert(mbegin <= (uint8_t*) v && (uint8_t*) v < mend);
|
||||
|
||||
c = ROUNDDOWN(v, PGSIZE);
|
||||
|
||||
while (uvpt[PGNUM(c)] & PTE_CONTINUED) {
|
||||
sys_page_unmap(0, c);
|
||||
c += PGSIZE;
|
||||
assert(mbegin <= c && c < mend);
|
||||
}
|
||||
|
||||
/*
|
||||
* c is just a piece of this page, so dec the ref count
|
||||
* and maybe free the page.
|
||||
*/
|
||||
ref = (uint32_t*) (c + PGSIZE - 4);
|
||||
if (--(*ref) == 0)
|
||||
sys_page_unmap(0, c);
|
||||
}
|
||||
|
||||
123
lab/lib/nsipc.c
Normal file
123
lab/lib/nsipc.c
Normal file
@@ -0,0 +1,123 @@
|
||||
#include <inc/ns.h>
|
||||
#include <inc/lib.h>
|
||||
#include <lwip/sockets.h>
|
||||
|
||||
#define debug 0
|
||||
|
||||
// Virtual address at which to receive page mappings containing client requests.
|
||||
#define REQVA 0x0ffff000
|
||||
union Nsipc nsipcbuf __attribute__((aligned(PGSIZE)));
|
||||
|
||||
// Send an IP request to the network server, and wait for a reply.
|
||||
// The request body should be in nsipcbuf, and parts of the response
|
||||
// may be written back to nsipcbuf.
|
||||
// type: request code, passed as the simple integer IPC value.
|
||||
// Returns 0 if successful, < 0 on failure.
|
||||
static int
|
||||
nsipc(unsigned type)
|
||||
{
|
||||
static envid_t nsenv;
|
||||
if (nsenv == 0)
|
||||
nsenv = ipc_find_env(ENV_TYPE_NS);
|
||||
|
||||
static_assert(sizeof(nsipcbuf) == PGSIZE);
|
||||
|
||||
if (debug)
|
||||
cprintf("[%08x] nsipc %d\n", thisenv->env_id, type);
|
||||
|
||||
ipc_send(nsenv, type, &nsipcbuf, PTE_P|PTE_W|PTE_U);
|
||||
return ipc_recv(NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
int
|
||||
nsipc_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
|
||||
{
|
||||
int r;
|
||||
|
||||
nsipcbuf.accept.req_s = s;
|
||||
nsipcbuf.accept.req_addrlen = *addrlen;
|
||||
if ((r = nsipc(NSREQ_ACCEPT)) >= 0) {
|
||||
struct Nsret_accept *ret = &nsipcbuf.acceptRet;
|
||||
memmove(addr, &ret->ret_addr, ret->ret_addrlen);
|
||||
*addrlen = ret->ret_addrlen;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
int
|
||||
nsipc_bind(int s, struct sockaddr *name, socklen_t namelen)
|
||||
{
|
||||
nsipcbuf.bind.req_s = s;
|
||||
memmove(&nsipcbuf.bind.req_name, name, namelen);
|
||||
nsipcbuf.bind.req_namelen = namelen;
|
||||
return nsipc(NSREQ_BIND);
|
||||
}
|
||||
|
||||
int
|
||||
nsipc_shutdown(int s, int how)
|
||||
{
|
||||
nsipcbuf.shutdown.req_s = s;
|
||||
nsipcbuf.shutdown.req_how = how;
|
||||
return nsipc(NSREQ_SHUTDOWN);
|
||||
}
|
||||
|
||||
int
|
||||
nsipc_close(int s)
|
||||
{
|
||||
nsipcbuf.close.req_s = s;
|
||||
return nsipc(NSREQ_CLOSE);
|
||||
}
|
||||
|
||||
int
|
||||
nsipc_connect(int s, const struct sockaddr *name, socklen_t namelen)
|
||||
{
|
||||
nsipcbuf.connect.req_s = s;
|
||||
memmove(&nsipcbuf.connect.req_name, name, namelen);
|
||||
nsipcbuf.connect.req_namelen = namelen;
|
||||
return nsipc(NSREQ_CONNECT);
|
||||
}
|
||||
|
||||
int
|
||||
nsipc_listen(int s, int backlog)
|
||||
{
|
||||
nsipcbuf.listen.req_s = s;
|
||||
nsipcbuf.listen.req_backlog = backlog;
|
||||
return nsipc(NSREQ_LISTEN);
|
||||
}
|
||||
|
||||
int
|
||||
nsipc_recv(int s, void *mem, int len, unsigned int flags)
|
||||
{
|
||||
int r;
|
||||
|
||||
nsipcbuf.recv.req_s = s;
|
||||
nsipcbuf.recv.req_len = len;
|
||||
nsipcbuf.recv.req_flags = flags;
|
||||
|
||||
if ((r = nsipc(NSREQ_RECV)) >= 0) {
|
||||
assert(r < 1600 && r <= len);
|
||||
memmove(mem, nsipcbuf.recvRet.ret_buf, r);
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int
|
||||
nsipc_send(int s, const void *buf, int size, unsigned int flags)
|
||||
{
|
||||
nsipcbuf.send.req_s = s;
|
||||
assert(size < 1600);
|
||||
memmove(&nsipcbuf.send.req_buf, buf, size);
|
||||
nsipcbuf.send.req_size = size;
|
||||
nsipcbuf.send.req_flags = flags;
|
||||
return nsipc(NSREQ_SEND);
|
||||
}
|
||||
|
||||
int
|
||||
nsipc_socket(int domain, int type, int protocol)
|
||||
{
|
||||
nsipcbuf.socket.req_domain = domain;
|
||||
nsipcbuf.socket.req_type = type;
|
||||
nsipcbuf.socket.req_protocol = protocol;
|
||||
return nsipc(NSREQ_SOCKET);
|
||||
}
|
||||
132
lab/lib/sockets.c
Normal file
132
lab/lib/sockets.c
Normal file
@@ -0,0 +1,132 @@
|
||||
#include <inc/lib.h>
|
||||
#include <lwip/sockets.h>
|
||||
|
||||
static ssize_t devsock_read(struct Fd *fd, void *buf, size_t n);
|
||||
static ssize_t devsock_write(struct Fd *fd, const void *buf, size_t n);
|
||||
static int devsock_close(struct Fd *fd);
|
||||
static int devsock_stat(struct Fd *fd, struct Stat *stat);
|
||||
|
||||
struct Dev devsock =
|
||||
{
|
||||
.dev_id = 's',
|
||||
.dev_name = "sock",
|
||||
.dev_read = devsock_read,
|
||||
.dev_write = devsock_write,
|
||||
.dev_close = devsock_close,
|
||||
.dev_stat = devsock_stat,
|
||||
};
|
||||
|
||||
static int
|
||||
fd2sockid(int fd)
|
||||
{
|
||||
struct Fd *sfd;
|
||||
int r;
|
||||
|
||||
if ((r = fd_lookup(fd, &sfd)) < 0)
|
||||
return r;
|
||||
if (sfd->fd_dev_id != devsock.dev_id)
|
||||
return -E_NOT_SUPP;
|
||||
return sfd->fd_sock.sockid;
|
||||
}
|
||||
|
||||
static int
|
||||
alloc_sockfd(int sockid)
|
||||
{
|
||||
struct Fd *sfd;
|
||||
int r;
|
||||
|
||||
if ((r = fd_alloc(&sfd)) < 0
|
||||
|| (r = sys_page_alloc(0, sfd, PTE_P|PTE_W|PTE_U|PTE_SHARE)) < 0) {
|
||||
nsipc_close(sockid);
|
||||
return r;
|
||||
}
|
||||
|
||||
sfd->fd_dev_id = devsock.dev_id;
|
||||
sfd->fd_omode = O_RDWR;
|
||||
sfd->fd_sock.sockid = sockid;
|
||||
return fd2num(sfd);
|
||||
}
|
||||
|
||||
int
|
||||
accept(int s, struct sockaddr *addr, socklen_t *addrlen)
|
||||
{
|
||||
int r;
|
||||
if ((r = fd2sockid(s)) < 0)
|
||||
return r;
|
||||
if ((r = nsipc_accept(r, addr, addrlen)) < 0)
|
||||
return r;
|
||||
return alloc_sockfd(r);
|
||||
}
|
||||
|
||||
int
|
||||
bind(int s, struct sockaddr *name, socklen_t namelen)
|
||||
{
|
||||
int r;
|
||||
if ((r = fd2sockid(s)) < 0)
|
||||
return r;
|
||||
return nsipc_bind(r, name, namelen);
|
||||
}
|
||||
|
||||
int
|
||||
shutdown(int s, int how)
|
||||
{
|
||||
int r;
|
||||
if ((r = fd2sockid(s)) < 0)
|
||||
return r;
|
||||
return nsipc_shutdown(r, how);
|
||||
}
|
||||
|
||||
static int
|
||||
devsock_close(struct Fd *fd)
|
||||
{
|
||||
if (pageref(fd) == 1)
|
||||
return nsipc_close(fd->fd_sock.sockid);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
connect(int s, const struct sockaddr *name, socklen_t namelen)
|
||||
{
|
||||
int r;
|
||||
if ((r = fd2sockid(s)) < 0)
|
||||
return r;
|
||||
return nsipc_connect(r, name, namelen);
|
||||
}
|
||||
|
||||
int
|
||||
listen(int s, int backlog)
|
||||
{
|
||||
int r;
|
||||
if ((r = fd2sockid(s)) < 0)
|
||||
return r;
|
||||
return nsipc_listen(r, backlog);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
devsock_read(struct Fd *fd, void *buf, size_t n)
|
||||
{
|
||||
return nsipc_recv(fd->fd_sock.sockid, buf, n, 0);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
devsock_write(struct Fd *fd, const void *buf, size_t n)
|
||||
{
|
||||
return nsipc_send(fd->fd_sock.sockid, buf, n, 0);
|
||||
}
|
||||
|
||||
static int
|
||||
devsock_stat(struct Fd *fd, struct Stat *stat)
|
||||
{
|
||||
strcpy(stat->st_name, "<sock>");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
socket(int domain, int type, int protocol)
|
||||
{
|
||||
int r;
|
||||
if ((r = nsipc_socket(domain, type, protocol)) < 0)
|
||||
return r;
|
||||
return alloc_sockfd(r);
|
||||
}
|
||||
@@ -101,6 +101,7 @@ spawn(const char *prog, const char **argv)
|
||||
// Create new child environment
|
||||
if ((r = sys_exofork()) < 0)
|
||||
return r;
|
||||
|
||||
// 父进程返回子进程的PID
|
||||
child = r;
|
||||
|
||||
@@ -305,6 +306,7 @@ static int
|
||||
copy_shared_pages(envid_t child)
|
||||
{
|
||||
// LAB 5: Your code here.
|
||||
|
||||
size_t pn;
|
||||
int r;
|
||||
struct Env *e;
|
||||
@@ -317,6 +319,7 @@ copy_shared_pages(envid_t child)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -117,3 +117,22 @@ sys_ipc_recv(void *dstva)
|
||||
return syscall(SYS_ipc_recv, 1, (uint32_t)dstva, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
unsigned int
|
||||
sys_time_msec(void)
|
||||
{
|
||||
return (unsigned int) syscall(SYS_time_msec, 0, 0, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
int
|
||||
sys_pkt_try_send(void *buf, size_t len)
|
||||
{
|
||||
return syscall(SYS_pkt_try_send, 1, (uint32_t)buf, (uint32_t)len, 0, 0, 0);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
sys_pkt_try_receive(void *rev_buf, size_t *len)
|
||||
{
|
||||
return syscall(SYS_pkt_try_recv, 1, (uint32_t)rev_buf, (uint32_t)len, 0, 0, 0);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user