write()系统调用和中断int 0x80

write()系统调用和中断int 0x80

1.引出问题:printf()的底层实现是什么:
我们经常使用printf(),今天来看一下printf()的底层:
在linux/init/main.c中:

static int printf(const char *fmt, ...)
{
	va_list args;
	int i;

	va_start(args, fmt);
	write(1,printbuf,i=vsprintf(printbuf, fmt, args));  //调用了write()
	va_end(args);
	return i;
}

2.write()的基本用法:
函数原型:

#include <unistd.h>
size_t write(int fileds,const void *buf,size_t nbytes);

一个简单示例:

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>

int main(){
    int num = 0;
    //1表示标准输出;20表示输出的字符串长度
    num = write(1,"This is write test\n",20);
    printf("%d\n",num);
}

3.查看write()的实现
查看的版本是linux 0.11(可以通过网址:https://elixir.bootlin.com/linux/0.11/sourcezai/lib/write.c 查看各个版本linux 代码)
write()实现在文件 linux/lib/write.c 中,可以看到是进一步调用了_syscall3() 函数:

/*
 *  linux/lib/write.c
 *
 *  (C) 1991  Linus Torvalds
 */

#define __LIBRARY__
#include <unistd.h>

_syscall3(int,write,int,fd,const char *,buf,off_t,count)

4.查看_syscall3() 函数
在文件 linux/include/unistd.h中:
注意:DPL>=CPL才可以执行代码

#define _syscall3(type,name,atype,a,btype,b,ctype,c) \
type name(atype a,btype b,ctype c) \
{ \
long __res; \
__asm__ volatile ("int $0x80" \
	: "=a" (__res) \
	: "0" (__NR_##name),"b" ((long)(a)),"c" ((long)(b)),"d" ((long)(c))); \
if (__res>=0) \
	return (type) __res; \
errno=-__res; \
return -1; \
}

进行宏展开之后是:

int write(int fd,const char * buf,off_t count) 
{ 
long __res; 
__asm__ volatile ("int $0x80" \
	: "=a" (__res) \
	: "0" (__NR_write),"b" ((long)(fd)),"c" ((long)(buf)),"d" ((long)(count))); 
if (__res>=0) 
	return (int) __res; 
errno=-__res; 
return -1; 
}

内嵌汇编简单解读:
输出:返回值是__res(eax寄存器的值放入__res)
输入:__NR_write__放入eax寄存器,fd放入ebx寄存器,buf放入ecx寄存器,count放入edx寄存器
__NR_write定义在linux/include/unistd.h 中:
一共定义了71个,列出10个供参考

#define __NR_setup	0	/* used only by init, to get system going */
#define __NR_exit	1
#define __NR_fork	2
#define __NR_read	3
#define __NR_write	4    //用到了这个
#define __NR_open	5
#define __NR_close	6
#define __NR_waitpid	7
#define __NR_creat	8
#define __NR_link	9
#define __NR_unlink	10

5最终调用sys_write()来实现printf()

int sys_write(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;
	inode=file->f_inode;
	if (inode->i_pipe)
		return (file->f_mode&2)?write_pipe(inode,buf,count):-EIO;
	if (S_ISCHR(inode->i_mode))
		return rw_char(WRITE,inode->i_zone[0],buf,count,&file->f_pos);
	if (S_ISBLK(inode->i_mode))
		return block_write(inode->i_zone[0],&file->f_pos,buf,count);
	if (S_ISREG(inode->i_mode))
		return file_write(inode,file,buf,count);
	printk("(Write)inode->i_mode=%06o\n\r",inode->i_mode);
	return -EINVAL;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值