linux *** 作系统中 使用系统调用的一般方式是怎样的?

linux *** 作系统中 使用系统调用的一般方式是怎样的?,第1张

给个例子给你看看吧,这里是linux中一个C语言程序,他用到了linux提供的系统调用,很长的程序了,或许你没耐心看,我在最后给你列出那些地方用了系统调用

#include <stdio.h>

#include <stdlib.h>

#include <unistd.h>

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/msg.h>

#define BUFF_LEN 1024

#define RET_ERROR 1

#define RET_OK 0

typedef struct msg_send_struct { //这就是一个消息的数据结构

long my_type//我们就是根据这个字段来区分每块消息的

char my_text[BUFF_LEN]

} msg_send_struct

int main() {

char * path = "/"

int i_porject_id = 7

key_t key

msg_send_struct msg_send//定义发送消息

int i_ret

int i_msg_id

int i_flag = 0666|IPC_CREAT//为消息管道的创建指定参数,IPC_CREAT表示这个消息队列是创建,而不是搜索已经存在的消息队列

key = ftok(path, i_porject_id)//为消息队列生成一个key,当然你也可以手动指定,当你运气很好没有和已经窜在的消息队列的key起冲突的时候

if(key == 1) {

printf("building key error\n")

exit(1)

}

i_msg_id = msgget(key, i_flag)//根据你的参数决定是创建还是搜索KEY值得消息队列

if(i_msg_id == -1) {

printf("create msg queue error\n")

exit(1)

}

printf("i_msg_id = %d\n", i_msg_id)

msg_send.my_type = 1

strcpy(msg_send.my_text, "hello world")//初始化消息

i_ret = msgsnd(i_msg_id, &msg_send, strlen("hello world") + 1, IPC_NOWAIT)//开始发送,nowait表示如果队列中消息满了当前进程不等待直接返回错误,反之很容易理解吧

if(i_ret == -1) {

printf("msg send error\n")

exit(1)

}

exit(0)

}

下面是系统调用:

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/msg.h>这些头文件可不是库函数,他里面就是linux提供的系统调用。

key = ftok(path, i_porject_id)//为消息队列生成一个key,当然你也可以手动指定,当你运气很好没有和已经窜在的消息队列的key起冲突的时候

linux中系统调用,利用文件系统和ID来创建KEY。

i_msg_id = msgget(key, i_flag)//根据i_flag值决定是创建还是寻找消息队列的系统调用。

i_ret = msgsnd(i_msg_id, &msg_send, strlen("hello world") + 1, IPC_NOWAIT)//发送消息的系统调用msgsnd函数。

这里涉及到进程通信中的消息队列内容,如果不明白没什么关系,可以看出来他和C的库函数调用一模一样,只不过实现方式,这需要你的知识积累到一定程度,有很大差别。对于一个程序员来说,我们看不出什么他们和库函数有什么区别,这算是一种对我们的透明性。

补充:这个例子是我写来学习进程通信内容的,由于采用了linux系统调用,所以只能在linux下面运行,还有就是我没有考虑权限问题,所以要编译请用超级用户root,由于消息队列的特性,这个程序没有释放队列(我把释放代码写在了接受消息的程序中),第2次运行就会报消息队列不能创建的错误。

.三种方法实现Linux系统调用

投稿:lijiao 字体:[增加 减小] 类型:转载 时间:2016-01-03 我要评论

这篇文章主要介绍了三种方法实现Linux系统调用,感兴趣的朋友可以参考一下

..系统调用(System Call)是 *** 作系统为在用户态运行的进程与硬件设备(如CPU、磁盘、打印机等)进行交互提供的一组接口。当用户进程需要发生系统调用时,CPU 通过软中断切换到内核态开始执行内核系统调用函数。下面介绍Linux 下三种发生系统调用的方法:

一、通过 glibc 提供的库函数

glibc 是 Linux 下使用的开源的标准 C 库,它是 GNU 发布的 libc 库,即运行时库。glibc 为程序员提供丰富的 API(Application Programming Interface),除了例如字符串处理、数学运算等用户态服务之外,最重要的是封装了 *** 作系统提供的系统服务,即系统调用的封装。那么glibc提供的系统调用API与内核特定的系统调用之间的关系是什么呢?

1.通常情况,每个特定的系统调用对应了至少一个 glibc 封装的库函数,如系统提供的打开文件系统调用 sys_open 对应的是 glibc 中的 open 函数;

2.其次,glibc 一个单独的 API 可能调用多个系统调用,如 glibc 提供的 printf 函数就会调用如 sys_open、sys_mmap、sys_write、sys_close 等等系统调用;

3.另外,多个 API 也可能只对应同一个系统调用,如glibc 下实现的 malloc、calloc、free 等函数用来分配和释放内存,都利用了内核的 sys_brk 的系统调用。

二、使用 syscall 直接调用

使用上面的方法有很多好处,首先你无须知道更多的细节,如 chmod 系统调用号,你只需了解 glibc 提供的 API 的原型;其次,该方法具有更好的移植性,你可以很轻松将该程序移植到其他平台,或者将 glibc 库换成其它库,程序只需做少量改动。

但有点不足是,如果 glibc 没有封装某个内核提供的系统调用时,我就没办法通过上面的方法来调用该系统调用。如我自己通过编译内核增加了一个系统调用,这时 glibc 不可能有你新增系统调用的封装 API,此时我们可以利用 glibc 提供的syscall 函数直接调用。该函数定义在 unistd.h 头文件中。。。三、通过 int 指令陷入

如果我们知道系统调用的整个过程的话,应该就能知道用户态程序通过软中断指令int 0x80 来陷入内核态(在Intel Pentium II 又引入了sysenter指令),参数的传递是通过寄存器,eax 传递的是系统调用号,ebx、ecx、edx、esi和edi 来依次传递最多五个参数,当系统调用返回时,返回值存放在 eax 中。


欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/yw/8215851.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-04-14
下一篇2023-04-14

发表评论

登录后才能评论

评论列表(0条)

    保存