系统调用
是用户程序和linux内核交互的接口,linux的系统调用有下面三种方式:
在x86与x86_64的系统中,都可以使用int $0x80指令来执行系统调用,参数使用如下:
x86_64引入了一个新指令syscall来执行系统调用,参数使用如下:
正常调用库函数( man 3 execve ),传参方式见 x86 调用约定
查看调用号:头文件 /usr/include/asm/unistd.h 内容如下,所以32位和64位的调用号可以分别在unistd_32.h和unistd_64.h中找到
查看参数: man 2 execve
以 execve 为例, man 2 execve 查看其接口如下: int execve(const char *pathname, char *const argv[], char *const envp[])
下面汇编实现了 execve("/bin/sh", 0, 0) :
32位:
64位:
给个例子给你看看吧,这里是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 0typedef 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_idint 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 *** 作系统里面的“系统调用”这一概念相当于Windows上面的API,这样你就明白了吧,懂编程的应该都知道Windows API是个什么东东。所不同的是Linux系统调用的需要包含头文件比较分散,这一点在使用时需要注意,不同的系统调用记得要#include对应的头文件。
评论列表(0条)