Почему адреса файлов, хранящихся на диске (vbox vm), различаются каждый раз, когда я просматриваю их?

Я знаю о ASLR, который каждый раз загружает программу в разные места памяти, однако я не уверен, почему это происходит в случае файлов, которые я сохранил на диске /dev/sda2 моей виртуальной машины Linux.

mp:projects-20:17:09-$ ./lseek_demo 
The end offset of file1 is 1268
The start  offset of file2 is 0
Diff between them is -1268
The mem address of file1 is 0x7ffce008e738
The mem address of file2 is 0x7ffce008e740


mp:projects-20:17:12-$ ./lseek_demo 
The end offset of file1 is 1268
The start  offset of file2 is 0
Diff between them is -1268
The mem address of file1 is 0x7fff9113e148
The mem address of file2 is 0x7fff9113e150

вот код, который я использую

#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <error.h>

void   offsets(const char* fname1,const char*  fname2)
{
        int fd0 = open(fname1, O_RDWR);
        int fd1 = open(fname2, O_RDWR);

        if (fd0 == -1 || fd1 == -1)
                perror("opne");

        off_t off_fd0 = lseek(fd0, -1, SEEK_END);
        off_t off_fd1 = lseek(fd1,0,SEEK_SET);


        close(fd0);
        close(fd1);

        printf ("The end offset of file1 is %ld\n The start  offset of file3 is %ld\n Diff between them is %ld\n",off_fd0, off_fd1,(off_fd1 - off_fd0));
        printf ("The mem address of file1 is %p\n The mem address of file2 is %p\n",&off_fd0,&off_fd1);
}

int main()
{
        offsets ("readme.txt","slack_space_calc.c");
        return 0;
}

Это составлено на ubuntu 6.8.0-38-generiC#38-Ubuntu

🤔 А знаете ли вы, что...
C широко используется в разработке операционных систем, включая UNIX и Linux.


1
56
1

Ответ:

Решено

Этот код:

        off_t off_fd0 = lseek(fd0, -1, SEEK_END);
        off_t off_fd1 = lseek(fd1,0,SEEK_SET);

объявляет две локальные переменные целочисленного типа со знаком (некоторая неуказанная длина в битах) и устанавливает для них возвращаемые значения lseek(). Эти переменные принудительно сохраняются в стеке с помощью кода ниже; подробнее об этом чуть позже.

Выражение &off_fd0 возвращает указатель на переменную off_fd0, а не адрес «файла». Итак, когда вы печатаете его с помощью %p, вы печатаете адрес памяти этой переменной стека.

Интересное примечание. Если вы удалили этот оператор печати, есть большая вероятность, что компилятор оптимизирует одну или обе переменные. Т.е. он сохранит возвращаемые значения вызовов lseek() в регистрах ЦП. В этот момент переменные вообще не имеют адреса. (Это зависит от того, какой компилятор вы используете, целевой архитектуры ЦП и уровня оптимизации, выбранного для компиляции.) Наличие выражения &off_fd0 вынудило компилятор выделить хранилище стека для этой переменной, и в процессе этого ваш код был немного менее эффективно, чем могло бы быть.

Что касается того, почему адрес этой переменной меняется от одного запуска к другому. Было время, когда это было не так: каждый раз, когда вы запускали программу, стек находился в одном и том же месте. Добро пожаловать в ASLR — даже стек перемещается.

Наконец, как насчет адреса самого файла? Ну, у него нет адреса в памяти, но можно сказать, что номера дисковых блоков содержимого файла представляют собой «адрес» файла. Если вы посмотрите на них, вы обнаружите, что файлы не перемещаются; они практически остаются на одном и том же месте на диске, хотя даже это не является непреложным правилом. Если вы хотите узнать номера этих дисковых блоков, тогда удачи. Каждый тип файловой системы имеет свой собственный способ получения информации, а также RAID и NAS, и изучение всего этого выходит за рамки этого ответа.