You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

572 lines
13 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/*
* linux/kernel/sys.c
*
* (C) 1991 Linus Torvalds
*/
#include <errno.h>
#include <linux/sched.h> //调度程序头文件。定义了任务结构task_struct,任务0的数据,
//还有一些有关描述符参数设置和获取的嵌入式汇编函数宏语言
#include <linux/tty.h>
#include <linux/kernel.h> //内核头文件
#include <asm/segment.h>
#include <sys/times.h>
#include <sys/utsname.h> //系统名称结构头文件
#include <asm/io.h>
#include <fcntl.h>
int sys_ftime()
{
return -ENOSYS;
}
int sys_break()
{
return -ENOSYS;
}
int sys_ptrace()
{
return -ENOSYS;
}
int sys_stty()
{
return -ENOSYS;
}
int sys_gtty()
{
return -ENOSYS;
}
int sys_rename()
{
return -ENOSYS;
}
int sys_prof()
{
return -ENOSYS;
}
int sys_setregid(int rgid, int egid)
{
if (rgid>0) {
if ((current->gid == rgid) ||
suser())
current->gid = rgid;
else
return(-EPERM);
}
if (egid>0) {
if ((current->gid == egid) ||
(current->egid == egid) ||
suser()) {
current->egid = egid;
current->sgid = egid;
} else
return(-EPERM);
}
return 0;
}
//设置进程组号
int sys_setgid(int gid)
{
/* return(sys_setregid(gid, gid)); */
if (suser())
current->gid = current->egid = current->sgid = gid;
else if ((gid == current->gid) || (gid == current->sgid))
current->egid = gid;
else
return -EPERM;
return 0;
}
int sys_acct()
{
return -ENOSYS;
}
int sys_phys()
{
return -ENOSYS;
}
int sys_lock()
{
return -ENOSYS;
}
int sys_mpx()
{
return -ENOSYS;
}
int sys_ulimit()
{
return -ENOSYS;
}
//返回从1970年1月1号 开始记时的时间值(s)
int sys_time(long * tloc)
{
int i;
i = CURRENT_TIME;
if (tloc) {
verify_area(tloc,4);
put_fs_long(i,(unsigned long *)tloc); //把时间值存储到用户空间
//段寄存器fs被默认地指向用户数据空间因此此函数可利用fs段寄存器来访问用户空间中的值
}
return i;
}
/*
* Unprivileged users may change the real user id to the effective uid
* or vice versa.
*/
int sys_setreuid(int ruid, int euid)
{
int old_ruid = current->uid;
if (ruid>0) {
if ((current->euid==ruid) ||
(old_ruid == ruid) ||
suser())
current->uid = ruid;
else
return(-EPERM);
}
if (euid>0) {
if ((old_ruid == euid) ||
(current->euid == euid) ||
suser()) {
current->euid = euid;
current->suid = euid;
} else {
current->uid = old_ruid;
return(-EPERM);
}
}
return 0;
}
int sys_setuid(int uid)
{
/* return(sys_setreuid(uid, uid)); */
if (suser())
current->uid = current->euid = current->suid = uid;
else if ((uid == current->uid) || (uid == current->suid))
current->euid = uid;
else
return -EPERM;
return(0);
}
int sys_stime(long * tptr)
{
if (!suser())
return -EPERM;
startup_time = get_fs_long((unsigned long *)tptr) - jiffies/HZ;
return 0;
}
//获取当前任务运行时间统计值
int sys_times(struct tms * tbuf)
{
if (tbuf) {
verify_area(tbuf,sizeof *tbuf);
put_fs_long(current->utime,(unsigned long *)&tbuf->tms_utime);
put_fs_long(current->stime,(unsigned long *)&tbuf->tms_stime);
put_fs_long(current->cutime,(unsigned long *)&tbuf->tms_cutime);
put_fs_long(current->cstime,(unsigned long *)&tbuf->tms_cstime);
}
return jiffies;
}
//设置程序在内存中的末端位置
int sys_brk(unsigned long end_data_seg)
{
//如果参数值大于代码结尾,并且小于(堆栈-16kb则设置新数据段结尾值
if (end_data_seg >= current->end_code &&
end_data_seg < current->start_stack - 16384)
current->brk = end_data_seg;
return current->brk;
}
/*
* This needs some heave checking ...
* I just haven't get the stomach for it. I also don't fully
* understand sessions/pgrp etc. Let somebody who does explain it.
*/
int sys_setpgid(int pid, int pgid)
{
int i;
if (!pid)
pid = current->pid;
if (!pgid)
pgid = current->pid;
for (i=0 ; i<NR_TASKS ; i++)
if (task[i] && task[i]->pid==pid) {
if (task[i]->leader)
return -EPERM;
if (task[i]->session != current->session)
return -EPERM;
task[i]->pgrp = pgid;
return 0;
}
return -ESRCH;
}
int sys_getpgrp(void)
{
return current->pgrp;
}
int sys_setsid(void)
{
if (current->leader && !suser())
return -EPERM;
current->leader = 1;
current->session = current->pgrp = current->pid;
current->tty = -1;
return current->pgrp;
}
int sys_getgroups()
{
return -ENOSYS;
}
int sys_setgroups()
{
return -ENOSYS;
}
int sys_uname(struct utsname * name)
{
static struct utsname thisname = {
"linux .0","nodename","release ","version ","machine "
};
int i;
if (!name) return -ERROR;
verify_area(name,sizeof *name);
for(i=0;i<sizeof *name;i++)
put_fs_byte(((char *) &thisname)[i],i+(char *) name); //用来访问用户程序的数据
return 0;
}
int sys_sethostname()
{
return -ENOSYS;
}
int sys_getrlimit()
{
return -ENOSYS;
}
int sys_setrlimit()
{
return -ENOSYS;
}
int sys_getrusage()
{
return -ENOSYS;
}
int sys_gettimeofday()
{
return -ENOSYS;
}
int sys_settimeofday()
{
return -ENOSYS;
}
int sys_umask(int mask)
{
int old = current->umask;
current->umask = mask & 0777;
return (old);
}
int sys_pipe2(void){
return 0;
}
int sys_sleep(unsigned int seconds){
sys_signal(SIGALRM,SIG_IGN);
sys_alarm(seconds);
sys_pause();
return 0;
}
// int sys_execve2(){
// return 0;
// }
/*获取目录的目录项*/
/*fd指目录描述符dirp指目录信息count指目录信息大小*/
int sys_getdents(unsigned int fd,struct linux_dirent *dirp,unsigned int count)
{
struct file *file;
struct m_inode *inode;
struct buffer_head *bh;
struct dir_entry *de;
struct linux_dirent *temp;
char * buf;
int i,len = 0,ret = 0;
if(!count)return -1;
if(fd>=NR_OPEN)return -1; /*fd超过进程最多打开文件数20*/
file=current->filp[fd];
if(!file)return -1;
inode = file->f_inode;
temp = (struct linux_dirent *)malloc(sizeof(struct linux_dirent)); //目录信息
buf = (char*)malloc(sizeof(struct linux_dirent));
bh = bread(inode->i_dev , inode->i_zone[0]); //读取指向的数据块
for (;ret<inode->i_size;ret += sizeof(struct dir_entry)){
if (len >= count-sizeof(struct linux_dirent))
break;
de = (struct dir_entry *)(bh->b_data + ret);/*de更新为当前目录项*/
if (!de->inode )/*如果节点号为空,就退出*/
continue;
/*用temp保存当前目录项信息*/
temp->d_ino = de->inode;
temp->d_off = 0;
temp->d_reclen = sizeof(struct linux_dirent);
strcpy(temp->d_name,de->name);
/*将数据写回到用户*/
memcpy(buf, temp, sizeof(struct linux_dirent));
for (i=0;i < sizeof(struct linux_dirent);i++){
put_fs_byte(*(buf+i), ((char*)dirp)+len+i); //用来访问用户程序的数据
}
len += sizeof(struct linux_dirent);
}
return len;
}
//参考find_entry
// int sys_getcwd(char* buf,size_t size){
// struct buffer_head *bh;
// struct dir_entry*de,*p_de;
// unsigned current_depth = 0;
// struct m_inode* current_ino;
// struct m_inode* parent_ino;
// char* t_buf,* tmp;
// int ret = 0;
// t_buf = (char*)malloc(256);
// strcpy(t_buf,"");
// for(;;){
// current_ino = namei(".");
// parent_ino = namei("..");
// if(current_ino == parent_ino) //找到了根节点
// break;
// sys_chdir("..");
// //read_inode(current_ino); 这是个静态函数
// //buf[current_depth++] = read_inode(current_ino);//根据节点号在当前目录查找文件read_inode
// bh = bread(parent_ino->i_dev,parent_ino->i_zone[0]);
// for(;ret<parent_ino->i_size;ret+=sizeof(struct dir_entry))
// {
// de = (struct dir_entry*)(bh->b_data + ret);
// if(!de->inode)break;
// if(de->inode == (current_ino->i_num)){
// strcpy(tmp,"/");
// strcat(tmp,de->name);
// strcat(tmp,t_buf);
// strcpy(t_buf,tmp);
// current_depth += NAME_LEN;
// break;
// }
// }
// //current_depth++;
// }
// int i;
// for(i = 0;t_buf[i];i++){
// put_fs_byte(t_buf[i],buf+i);
// }
// return (int)buf;
// }
#define BUF_MAX 256
int sys_getcwd(char * buf, size_t size)
{
char temp[BUF_MAX], t_buf[BUF_MAX];
int flag,len;
struct m_inode *parent_ino,*current_ino,*root;
struct super_block *sb;
struct dir_entry *de,*p_de;
int i;
sb = (struct super_block *)bread(current->pwd->i_dev,1);
current_ino = current->pwd;
root = current->root;
while(current_ino->i_num != root->i_num)
{
de = (struct dir_entry *)bread(current_ino->i_dev,current_ino->i_zone[0])->b_data;
int de_num = current_ino->i_size/sizeof(struct dir_entry);//当前目录的目录项数量
flag = 0;
for(i=0;i<de_num;i++){
if(!strcmp((de+i)->name,"..")){
flag = 1;
parent_ino = iget(current_ino->i_dev,(de + i)->inode); //寻找父目录节点
break;
}
}
if(!flag) {
return NULL;
}
p_de = (struct dir_entry *)bread(parent_ino->i_dev,parent_ino->i_zone[0])->b_data;
int p_de_num = parent_ino->i_size/sizeof(struct dir_entry); //父目录的目录项数量
flag = 0;
for(i=0;i<p_de_num;i++){
if((p_de+i)->inode == current_ino->i_num){ //比对当前节点的节点号相同,则记录,并回溯
memset(temp, 0, sizeof(temp));
strcat(temp,"/");
strcat(temp,(p_de+i)->name);
strcat(temp,t_buf);
strncpy(t_buf,temp,BUF_MAX);
flag = 1;
break;
}
}
if(!flag){
return NULL;
}
current_ino = parent_ino;
}
for(i=0;i<strlen(t_buf);i++){
put_fs_byte(t_buf[i],buf+i);
}
return (int)buf;
}
/*
start:映射起始位置
len:长度
prot:映射的内存保护⽅式可取PROT_EXEC, PROT_READ, PROT_WRITE, PROT_NONE
flags:映射是否与其他进程共享的标志可取MAP_FILE, MAP_SHARED, MAP_PRIVATE
fd:⽂件句柄,文件描述符,代表要映射的文件
off:⽂件偏移量
返回值:成功返回已映射区域的指针,失败返回-1;
内存映射函数mmap, 负责把文件内容映射到进程的虚拟内存空间, 通过对这段内存的读取和修改,
来实现对文件的读取和修改,而不需要再调用readwrite等操作。
PROT_EXEC: 映射区可被执行
PROT_READ: 映射区可被读取
PROT_WRITE: 映射区可被写入
MAP_SHARED:写入映射区的数据会复制回文件, 且允许其他映射该文件的进程共享。
MAP_PRIVATE:对映射区的写入操作会产生一个映射区的复制(copy-on-write),
对此区域所做的修改不会写回原文件。
*/
// typedef struct { unsigned long pgprot; } pgprot_t;
// struct vm_area_struct{
// unsigned long vm_start; //虚拟内存起始地址
// unsigned long vm_end;
// unsigned long vm_flags; //该区域的标志
// pgprot_t vm_page_prot;
// };
// int memdev_mmap(struct file*filp,struct vm_area_struct *vma){
// vma->vm_flags |= VM_IO;
// vma->vm_flags |= VM_RESEVED;
// if(remap_pfn_range(vma,vma->vm_start,virt_to_phys(dev->data)>>PAGE_SHIFT,
// size,vma->vm_page_prot))
// return -EAGAIN;
// return 0;
// }
int sys_mmap(void* start,size_t len,int prot,int flags,
int fd,off_t off){
return 0;
};
#define vga_graph_memstart 0xA0000
#define vga_graph_memsize 64000
#define cursor_side 6
#define width 320
#define height 200
//#define barrier_width 10
int volatile jumpp;
int flag=0;
int sys_init_graphics()
{
int i,j,x,y;
char *p=vga_graph_memstart;
x = 20;y = 20;
if(flag==0)
{
/* 图形控制器拼接器有关寄存器端口是0x3CE和0x3C4 */
/* 先往寄存器端口写索引号,端口地址下一个写命令或读入数据 */
/* 在0x3CE端口中有对应索引号0x06的寄存器
第0位用来控制字符模式,1启动图形模式;2,3位决定显存位置*/
/* 0x3CE中索引号0x05的寄存器
第六位设置为1设定为256色*/
outb(0x05,0x3CE);
outb(0x40,0x3CF);/* 设定256色且取出方式为移动拼装*/
/*显存区域 A0000H - AFFFFH(64KB) */
outb(0x06,0x3CE);
outb(0x05,0x3CF);/*设定现存的地址区域,禁止字符模式*/
/*0x4C4下的索引号为0x04的寄存器
第四位为chain4用于将4个显存片连在一起*/
outb(0x04,0x3C4);
outb(0x08,0x3C5);/*设定将4个现存片连在一起*/
/*设置End Horizontal Display 为79*/
/*用于控制在屏幕上显示的扫描线长度 */
outb(0x01,0x3D4);
outb(0x4F,0x3D5);
/*0x03寄存器,0-4位表示End Horizontal Blanking
5,6位表示Display Enable Skew;7位表示EVRA*/
outb(0x03,0x3D4);
outb(0x82,0x3D5); //设置Skew 为0
outb(0x07,0x3D4);
outb(0x1F,0x3D5);/*vertical display end No8,9 bit=1,0*/
outb(0x12,0x3D4);
outb(0x8F,0x3D5);/*vertical display end low 7b =0x8F*/
/*CRT控制器中索引号为0x17的寄存器中的SLDIV位设置为1,
Scanline Counter加一的周期为两个扫描周期*/
outb(0x17,0x3D4);
outb(0xA3,0x3D5);/*SLDIV=1 ,scanline clock/2*/
outb(0x14,0x3D4);
outb(0x40,0x3D5);/*DW=1*/
/*移动距离 = 2*Memory Address Size
* Offset Register/Pixels Per Address*/
outb(0x13,0x3D4);
outb(0x28,0x3D5);/*Offset=40, 20:bian chang*/
/*开始绘制屏幕*/
outb(0x0C,0x3D4);
outb(0x00,0x3D5);
outb(0x0D,0x3D4);
outb(0x00,0x3D5);/*Start Address=0xA0000*/
flag=1;
}
for(i=0;i<vga_graph_memsize;i++) *p++=3; //背景为蓝色
//3-blue 4-red 12-purple
for(i=x-cursor_side;i<=x+cursor_side;i++)
for(j=y-cursor_side;j<=y+cursor_side;j++){
p=(char *) vga_graph_memstart+j*width+i;
*p=12; //鼠标为红色
}
return 0;
}
int sys_get_message(){
return 0;
}