cp命令实现的一些惨案—父子进程共享资源问题

前述:计划是研究linux的ipc技术的,想来倒不如直接动手实现cp/scp命令,然后不断升级改进,最后把技术学了,顺便熟悉下常见的api接口

思路:

char buffer[64k]
char *fp = &buffer;
int rflag = 0;
int *rp = &rflag;

pid = fork()
if pid > 0 ; then
    使用fread()从文件中读取内容到buffer中
    设置rflag = 1
    循环等待 rflag 被子进程设置为0
    继续执行上述循环
else
    循环检测*rp也就是rflag的内容是否为1
    为1则 *fp写到目标文件中
    设置*rp  = 0

本来想就算写时拷贝,只要我有指针子进程就可以为所欲为了,结果没想到调试的时侯直接给我个锤子

实现:

#include <sys/types.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

#define READBLOCK 64*1024

int main(int argc, char *argv[])
{

    char buffer[READBLOCK];
    const char *pb = buffer; 
    int rflag = 0;
    int *lock = &rflag;

    pid_t pid = fork();
    if(pid > 0)
    {
        while(1)
        {
            rflag = 1;
            printf("p &rflag = %x\n", &rflag);
            sleep(1);
            rflag = 3;
            printf("p &rflag = %x\n", &rflag);
            sleep(1);
        }
    }
    else if( pid == 0)
    {
        while(1)
        {
            printf("child pid , lock = %x, rflag=%d\n", lock, *lock);
            sleep(1);
        }
    }
    
    return 0;
}

调试时父子进程打印rflag的地址都是一样的,但是内容却不一样,子进程为0,父进程为1,3。

子进程如下

(gdb) i locals
sfp = <optimized out>
dfp = <optimized out>
r = <optimized out>
buffer = '\000' <repeats 60296 times>...
pb = 0x7ffc4a7105d0 ""
rflag = 0
lock = 0x7ffc4a7105b8
pid = 0
(gdb) p rflag
$2 = 0
(gdb) p &rflag
$3 = (int *) 0x7ffc4a7105b8
(gdb) p *(int*) 0x7ffc4a7105b8
$4 = 0
(gdb) p *(int*)0x7ffc4a7105b8
$5 = 0

父进程如下:

gdb) i locals
sfp = <optimized out>
dfp = <optimized out>
r = <optimized out>
buffer = '\000' <repeats 60296 times>...
pb = 0x7ffc4a7105d0 ""
rflag = 0
lock = 0x7ffc4a7105b8
pid = 3435090
(gdb) p &rflags
No symbol "rflags" in current context.
(gdb) p &rflag
$1 = (int *) 0x7ffc4a7105b8
(gdb) s
85                printf("p &rflag = %x\n", &rflag);
(gdb) i locals
sfp = <optimized out>
dfp = <optimized out>
r = <optimized out>
buffer = '\000' <repeats 60296 times>...
pb = 0x7ffc4a7105d0 ""
rflag = 3
lock = 0x7ffc4a7105b8
pid = 3435090
(gdb) p &rflag
$2 = (int *) 0x7ffc4a7105b8
(gdb) p *(int *) 0x7ffc4a7105b8
$3 = 3

总的来说,哪怕用指针保留内存块的地址,然后fork(),之后就算想用从未修改过内容的指针来瞒天过海访问父进程的内容,也不行,这应该是写时复制的真正含义

 

posted @ 2022-05-13 19:45  桃花春风一杯酒  阅读(65)  评论(0)    收藏  举报