int sys_read(unsigned int fd,char * buf,int count)
{
struct file * file;
struct m_inode * inode;
if (fd>=NR_OPEN || count<0 file="current-">filp[fd]))
return -EINVAL;
if (!count)
return 0;
verify_area(buf,count);
inode = file->f_inode;
if (inode->i_pipe)
return (file->f_mode&1)?read_pipe(inode,buf,count):-EIO; /* pipe mode hadn't been added in stat.h*/
if (S_ISCHR(inode->i_mode))
return rw_char(READ,inode->i_zone[0],buf,count,&file->f_pos);
if (S_ISBLK(inode->i_mode))
return block_read(inode->i_zone[0],&file->f_pos,buf,count); /*
if (S_ISDIR(inode->i_mode) || S_ISREG(inode->i_mode)) {
if (count+file->f_pos > inode->i_size)
count = inode->i_size - file->f_pos; /*truncate to the boundary*/
if (count<=0)
return 0;
return file_read(inode,file,buf,count);
}
printk("(Read)inode->i_mode=%06o\n\r",inode->i_mode);
return -EINVAL;
}
1.what does inode->i_zone[0] contain ?
it stores character/block's logical device number as oppose of logical block number in regular file.
2.file points to a global file entry, if the offset was modified in this process, will other processes be affected ?
3. we can treat directory as regular file.
To summarize this function, in linux there're basic 4 types of readable things: 1.pipe 2.character device 3.block device 4.directory and regular file.
pipe resides on memory area, it normally has two ends. one for reading, one for writing.
4. some perpheral apparatus have its own buffer, which could facilitate the data transmission. how to fetch data out of the buffer ?
5.why the code verifies the buf ?
buf value assigns to the function is the logical address. get_base(current->ldt[2]); translates logical address to virtual address.
void verify_area(void * addr,int size)
{
unsigned long start;
start = (unsigned long) addr;
size += start & 0xfff; /* fully align to block boundary*/
start &= 0xfffff000; /* locate which block the addr is belonging to */
start += get_base(current->ldt[2]);
while (size>0) {
size -= 4096;
write_verify(start);
start += 4096;
}
}
int read_pipe(struct m_inode * inode, char * buf, int count)
{
int chars, size, read = 0;
while (count>0) {
while (!(size=PIPE_SIZE(*inode))) {
wake_up(&inode->i_wait);
if (inode->i_count != 2) /* are there any writers? */
return read;
sleep_on(&inode->i_wait);
}
chars = PAGE_SIZE-PIPE_TAIL(*inode);
if (chars > count)
chars = count;
if (chars > size)
chars = size;
count -= chars;
read += chars;
size = PIPE_TAIL(*inode);
PIPE_TAIL(*inode) += chars;
PIPE_TAIL(*inode) &= (PAGE_SIZE-1);
while (chars-->0)
put_fs_byte(((char *)inode->i_size)[size++],buf++);
}
wake_up(&inode->i_wait);
return read;
}
1.what if count is greater than chars ?
in such case, the reading action will repeat.
2.what i_zone[0] and i_zone[1] represent in pipe inode ? an memory address or an integer ?
Theoretically speaking, i_zone[0/1] only could contain integre, which is used to index in array.
PIPE_TAIL(*inode) &= (PAGE_SIZE-1); if reading or writing operation exceeds the upper side boundary, the pointer will wrap around to the beginning of the pipe buffer.
this piece code is much like
while (PIPE_TAIL(*inode) > ( PAGE_SIZE-1 ) )
PIPE_TAIL(*inode) = PIPE_TAIL(*inode) - (PAGE_SIZE-1 ) ;
size : the available amount
chars : represent the distance of tail or head to the upper side of pipe buffer. Note, it doesn't stand for the amount of pipe data.
Thursday, January 28, 2010
Tuesday, January 26, 2010
Subscribe to:
Posts (Atom)