程序是怎么装载到内存并被运行的

在后续所有内容之前,我们需要先达成一个共识,所有的程序都是被装载进内存然后才被使用的。装载器会把对应的指令和数据加载到内存里面来,让 CPU 去执行,而程序,包括操作系统就是一堆指令和数据的集合。下面开始套娃,BIOS硬件初始化并开始加载主引导扇区(多系统需要选择启动哪个系统的原因),将操作系统加载到内存;移交加载控制权给操作系统,操作系统开始装载非操作系统程序到内存。因为Linux和Windows系统的装载器不同,所以这也是为什么Windows上的一部分程序没法在Linux上跑的原因,如.exe。
摘要由CSDN通过智能技术生成

在后续所有内容之前,我们需要先达成一个共识,所有的程序都是被装载进内存然后才被使用的。装载器会把对应的指令和数据加载到内存里面来,让 CPU 去执行,而程序,包括操作系统就是一堆指令和数据的集合。

下面开始套娃,BIOS硬件初始化并开始加载主引导扇区(多系统需要选择启动哪个系统的原因),将操作系统加载到内存;移交加载控制权给操作系统,操作系统开始装载非操作系统程序到内存。因为Linux和Windows系统的装载器不同,所以这也是为什么Windows上的一部分程序没法在Linux上跑的原因,如.exe。

装载器需要满足两个要求。

第一,可执行程序加载后占用的内存空间应该是连续的,方便寻址。

第二,我们需要同时加载很多个程序,并且不能让程序自己规定在内存中加载的位置,避免冲突。

于是我们可以在内存里面,找到一段连续的内存空间,然后分配给装载的程序,然后把这段连续的内存空间地址,和整个程序指令里指定的内存地址做一个映射。我们把指令里用到的内存地址叫作虚拟内存地址(Virtual Memory Address),实际在内存硬件里面的空间地址,我们叫物理内存地址(Physical Memory Address)。程序里有指令和各种内存地址,我们只需要关心虚拟内存地址就行了。

我们维护一个虚拟内存到物理内存的映射表,这样实际程序指令执行的时候,

  • 19
    点赞
  • 86
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个简单的模拟设备驱动程序的代码示例,该驱动程序将创建一个名为 "mydevice" 的字符设备,并支持读取和写入操作: ```c #include <linux/module.h> #include <linux/kernel.h> #include <linux/fs.h> #include <linux/uaccess.h> #define DEVICE_NAME "mydevice" #define BUFFER_SIZE 1024 static char device_buffer[BUFFER_SIZE]; static int pos = 0; static int device_open(struct inode *inode, struct file *file) { printk(KERN_INFO "Device opened\n"); return 0; } static int device_release(struct inode *inode, struct file *file) { printk(KERN_INFO "Device closed\n"); return 0; } static ssize_t device_read(struct file *file, char *buffer, size_t length, loff_t *offset) { int bytes_read = 0; if (pos >= BUFFER_SIZE) { return 0; } while (length && pos < BUFFER_SIZE) { put_user(device_buffer[pos], buffer++); length--; pos++; bytes_read++; } return bytes_read; } static ssize_t device_write(struct file *file, const char *buffer, size_t length, loff_t *offset) { int bytes_written = 0; if (pos >= BUFFER_SIZE) { return -ENOSPC; } while (length && pos < BUFFER_SIZE) { get_user(device_buffer[pos], buffer++); length--; pos++; bytes_written++; } return bytes_written; } static struct file_operations fops = { .open = device_open, .release = device_release, .read = device_read, .write = device_write, }; static int __init mydevice_init(void) { int ret = register_chrdev(0, DEVICE_NAME, &fops); if (ret < 0) { printk(KERN_ALERT "Failed to register device\n"); return ret; } printk(KERN_INFO "Device registered\n"); return 0; } static void __exit mydevice_exit(void) { unregister_chrdev(0, DEVICE_NAME); printk(KERN_INFO "Device unregistered\n"); } module_init(mydevice_init); module_exit(mydevice_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Your Name"); MODULE_DESCRIPTION("A simple device driver"); ``` 将上述代码保存为 mydevice.c 文件,并在终端中使用以下命令编译为内核模块: ```bash make -C /lib/modules/$(uname -r)/build M=$(pwd) modules ``` 编译成功后,将会生成名为 mydevice.ko 的内核模块文件。接下来,使用以下命令将该模块装载内存中: ```bash sudo insmod mydevice.ko ``` 使用以下命令查看模块是否成功装载: ```bash lsmod | grep mydevice ``` 最后,可以编写一个用户程序来调用该模块,以下是一个简单的示例程序: ```c #include <stdio.h> #include <fcntl.h> #include <unistd.h> #define DEVICE_PATH "/dev/mydevice" #define BUFFER_SIZE 1024 int main() { int fd = open(DEVICE_PATH, O_RDWR); if (fd == -1) { perror("Failed to open device"); return 1; } char buffer[BUFFER_SIZE]; int bytes_read = read(fd, buffer, BUFFER_SIZE); if (bytes_read == -1) { perror("Failed to read from device"); return 1; } printf("Read %d bytes from device: %s\n", bytes_read, buffer); char *message = "Hello, device!"; int bytes_written = write(fd, message, strlen(message)); if (bytes_written == -1) { perror("Failed to write to device"); return 1; } printf("Wrote %d bytes to device\n", bytes_written); close(fd); return 0; } ``` 该程序将打开 mydevice 设备,并进行读取和写入操作。将上述代码保存为 myprogram.c 文件,并使用以下命令编译: ```bash gcc -o myprogram myprogram.c ``` 编译成功后,可以运行程序: ```bash ./myprogram ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值