my solution to lab 6

This commit is contained in:
winPond
2019-07-17 16:08:06 +08:00
parent 8147d99448
commit c62da1c86d
534 changed files with 60875 additions and 6513 deletions

View File

@@ -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

View File

@@ -126,6 +126,7 @@ fd_close(struct Fd *fd, bool must_exist)
static struct Dev *devtab[] =
{
&devfile,
&devsock,
&devpipe,
&devcons,
0

View File

@@ -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
View 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
View 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
View 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);
}

View File

@@ -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;
}

View File

@@ -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);
}