一.添加信号量系统调用
1.修改unistd.h,如系统调用实验,需要将unistd.h的改动写到bochs中
/* add */
#include <sys/sem.h>
/* end */
/* add */
#define __NR_sem_open 72
#define __NR_sem_wait 73
#define __NR_sem_post 74
#define __NR_sem_unlink 75
/* end */
/* add */
sem_t *sem_open(const char *name, unsigned int value);
int sem_wait(sem_t *sem);
int sem_post(sem_t *sem);
int sem_unlink(const char *name);
/* end */
2.新建sem.h
在include/sys/目录下新建sem.h
/* add by jlb */
#ifndef _SEM_H
#define _SEM_H
/* include task_struct */
#include <linux/sched.h>
#define NAME_SIZE 10
/* add */
typedef struct { char name[NAME_SIZE]; unsigned int value; struct task_struct *wait; char used; } sem_t;
/* end */
#endif
3.修改system_call.s
/* mod by jlb */
nr_system_calls = 76
4.修改sys.h
/* add */
extern int sys_sem_open();
extern int sys_sem_wait();
extern int sys_sem_post();
extern int sys_sem_unlink();
/* end */
fn_ptr sys_call_table[] = { sys_setup, ......
sys_setregid, sys_sem_open, sys_sem_wait, sys_sem_post, sys_sem_unlink };
5.新增sem.c
kernel/目录下新建sem.c
/* add by jlb */
#include <sys/sem.h>
#include <errno.h>
/* include get_fs_byte() */
#include <asm/segment.h>
/* include NULL */
#include <unistd.h>
/* include cli() sti() */
#include <asm/system.h>
/* include prknik() */
#include <linux/kernel.h>
#define KSEM_SIZE 5
sem_t ksem[KSEM_SIZE] = {{{'0', }, 0, NULL, 0}, {{'\0', }, 0, NULL, 0}, {{'0', }, 0, NULL, 0}, {{'0', }, 0, NULL, 0}, {{'0', }, 0, NULL, 0}};
char buf[NAME_SIZE];
int str_equ(const char * sa,const char * sb)
{
int i;
for (i=0; sa[i] && sb[i]; i++)
if (sa[i] != sb[i])
return 0;
return 1;
}
void str_cpy(char * dest,const char * src)
{
int i;
for (i=0; dest[i] = src[i]; i++) ;
}
sem_t * sys_sem_open(const char *name, unsigned int value)
{
int i;
/* get name */
for (i=0; buf[i] = get_fs_byte(name+i); i++) ;
/* return old sem */
for (i=0; i<KSEM_SIZE; i++)
if (ksem[i].used) {
if (str_equ(ksem[i].name, buf)) {
/* debug */
printk("old: buf: %s\n", buf);
printk("old: %s, %d, %d, %d\n", ksem[i].name, ksem[i].value, ksem[i].wait, ksem[i].used);
return &ksem[i];
}
}
/* create new sem */
for (i=0; i<KSEM_SIZE; i++)
if (!ksem[i].used) {
str_cpy(ksem[i].name, buf);
ksem[i].value = value;
ksem[i].wait = NULL;
ksem[i].used = 1;
/* debug */
printk("new: %s\n", buf);
printk("new: %s, %d, %d, %d\n", ksem[i].name, ksem[i].value, ksem[i].wait, ksem[i].used);
return &ksem[i];
}
/* no sem */
return NULL;
}
int sys_sem_wait(sem_t *sem)
{
cli();
while (!sem->value)
sleep_on(&sem->wait);
sem->value--;
sti();
return 0;
}
int sys_sem_post(sem_t *sem)
{
cli();
if (!sem->value)
wake_up(&sem->wait);
sem->value++;
sti();
return 0;
}
int sys_sem_unlink(const char *name)
{
int i;
/* get name */
for (i=0; buf[i] = get_fs_byte(name+i); i++) ;
/* try to delete sem */
for (i=0; i<KSEM_SIZE; i++)
if (ksem[i].used)
if (str_equ(ksem[i].name, buf)) {
ksem[i].used = 0;
return 0;
}
return -ERROR;
}
6.修改makefile
# mod by jlb
OBJS = sched.o system_call.o traps.o asm.o fork.o \
panic.o printk.o vsprintf.o sys.o exit.o \
signal.o mktime.o sem.o
copy
# mod by jlb
sem.s sem.o : sem.c ../include/sys/sem.h ../include/errno.h ../include/asm/segment.h \
../include/unistd.h ../include/linux/sched.h ../include/asm/system.h ../include/linux/kernel.h
二 编写pc.c
#define __LIBRARY__
#include <unistd.h>
/* include some constant */
#include <fcntl.h>
/* include printf() fflush() */
#include <stdio.h>
#include <sys/sem.h>
_syscall0(int, fork)
_syscall0(int, getpid)
_syscall3(int, write, int, fildes, const char *, buf, off_t, count)
_syscall3(int, read, int, fildes, char *, buf, off_t, count)
_syscall3(int, lseek, int, fildes, off_t, offset, int, origin)
_syscall0(int, sync);
_syscall2(sem_t *, sem_open, const char *, name, unsigned int, value)
_syscall1(int, sem_wait, sem_t *, sem)
_syscall1(int, sem_post, sem_t *, sem)
_syscall1(int, sem_unlink, const char *, name)
#define BUF_SIZE 10
#define FILE_BUF_SIZE 10
int main(void)
{
int pid;
int fd_p, fd_c;
/* count used by producer 1 */
unsigned short count = 0;
/* used by all consumers */
unsigned short tmp = 0;
unsigned char buf[BUF_SIZE] = {0};
/* empty = 10, full = 0, mutex = 1. above 1 is unlocked, 0 is locked */
char name_empty[10] = "empty";
char name_full[10] = "full";
char name_mutex[10] = "mutex";
sem_t * empty, * full, * mutex;
/* file, read and write */
fd_p = open("./f", O_CREAT|O_TRUNC|O_RDWR, 0666);
fd_c = open("./f", O_CREAT|O_TRUNC|O_RDWR, 0666);
/* close old semaphore */
sem_unlink(name_empty);
sem_unlink(name_full);
sem_unlink(name_mutex);
/* open new semaphore */
empty = sem_open(name_empty, FILE_BUF_SIZE);
full = sem_open(name_full, 0);
mutex = sem_open(name_mutex, 1);
/* consumer 1 */
if (!fork()) {
pid = getpid();
while (1) {
sem_wait(full);
sem_wait(mutex);
read(fd_c, buf, sizeof(unsigned short));
/* lower | higher */
tmp = (unsigned short)buf[0] | ((unsigned short)buf[1] << 8);
/* debug
printf("%d, %d\n", (unsigned short)buf[0], (unsigned short)buf[1] << 8);
*/
printf("Consumer 1 process %d : %d\n", pid, tmp);
fflush(stdout);
/* set file pos is 0 */
if (tmp % FILE_BUF_SIZE == 9)
lseek(fd_c, 0, SEEK_SET);
sem_post(mutex);
sem_post(empty);
}
return 0;
}
/* consumer 2 */
if (!fork()) {
pid = getpid();
while (1) {
sem_wait(full);
sem_wait(mutex);
read(fd_c, buf, sizeof(unsigned short));
/* lower | higher */
tmp = (unsigned short)buf[0] | ((unsigned short)buf[1] << 8);
/* debug
printf("%d, %d\n", (unsigned short)buf[0], (unsigned short)buf[1] << 8);
*/
printf("Consumer 2 process %d : %d\n", pid, tmp);
fflush(stdout);
/* set file pos is 0 */
if (tmp % FILE_BUF_SIZE == 9)
lseek(fd_c, 0, SEEK_SET);
sem_post(mutex);
sem_post(empty);
}
return 0;
}
/* consumer 3 */
if (!fork()) {
pid = getpid();
while (1) {
sem_wait(full);
sem_wait(mutex);
read(fd_c, buf, sizeof(unsigned short));
/* lower | higher */
tmp = (unsigned short)buf[0] | ((unsigned short)buf[1] << 8);
/* debug
printf("%d, %d\n", (unsigned short)buf[0], (unsigned short)buf[1] << 8);
*/
printf("Consumer 3 process %d : %d\n", pid, tmp);
fflush(stdout);
/* set file pos is 0 */
if (tmp % FILE_BUF_SIZE == 9)
lseek(fd_c, 0, SEEK_SET);
sem_post(mutex);
sem_post(empty);
}
return 0;
}
/* producer 1 */
pid = getpid();
while (count <= 500) {
sem_wait(empty);
sem_wait(mutex);
/* get lower */
buf[0] = (unsigned char)count;
/* get higher */
buf[1] = (unsigned char) (count >> 8);
write(fd_p, buf, sizeof(unsigned short));
sync();
/* debug
printf("%d, %d\n", buf[0], buf[1]);
printf("Producer 1 process %d : %d\n", pid, count);
fflush(stdout);
*/
/* set file pos is 0 */
if (count % FILE_BUF_SIZE == 9)
lseek(fd_p, 0, SEEK_SET);
count++;
sem_post(mutex);
sem_post(full);
}
return 0;
}
运行
./run
gcc -o pc pc.c
./pc >1.log
more 1.log