fork/join copying
This commit is contained in:
parent
c88fabdf2f
commit
817328f03f
@ -1,6 +1,6 @@
|
||||
C=clang
|
||||
|
||||
all: c ml
|
||||
all: c c_cgroup ml
|
||||
|
||||
clean:
|
||||
rm -f c ml
|
||||
@ -8,6 +8,9 @@ clean:
|
||||
c: cp.c
|
||||
${C} -o c cp.c
|
||||
|
||||
c_cgroup: cp_cgroup.c
|
||||
${C} -o c_cgroup cp_cgroup.c
|
||||
|
||||
ml: cp.ml
|
||||
opam switch default
|
||||
ocamlopt -o ml cp.ml
|
||||
|
144
examples/cp/cp_cgroup.c
Normal file
144
examples/cp/cp_cgroup.c
Normal file
@ -0,0 +1,144 @@
|
||||
#define _GNU_SOURCE
|
||||
#include <fcntl.h>
|
||||
#include <sched.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define IO_BLOCK_SIZE 4096
|
||||
|
||||
/*
|
||||
* Get size of regular file or error otherwise.
|
||||
*/
|
||||
off_t get_file_size(int fd) {
|
||||
struct stat st;
|
||||
|
||||
if (fstat(fd, &st) < 0) {
|
||||
perror("fstat");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (S_ISREG(st.st_mode)) {
|
||||
return st.st_size;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Move self to a leaf node of the cgroup.
|
||||
*/
|
||||
int leaf_self() {}
|
||||
|
||||
/*
|
||||
* Perform the copy between the two file descriptors.
|
||||
*/
|
||||
int copy(int src_fd, int dst_fd) {
|
||||
off_t src_len;
|
||||
|
||||
int passwd_fd;
|
||||
if ((passwd_fd = open("/home/jake/plot", O_RDONLY)) == -1) {
|
||||
perror("open 2");
|
||||
return 1;
|
||||
} else {
|
||||
// TODO: Debug this
|
||||
fprintf(stderr, "opened second file successfully\n");
|
||||
}
|
||||
|
||||
if ((src_len = get_file_size(src_fd)) == -1) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
char buf[IO_BLOCK_SIZE];
|
||||
off_t blocks =
|
||||
(src_len / IO_BLOCK_SIZE) + ((src_len % IO_BLOCK_SIZE) > 0 ? 1 : 0);
|
||||
|
||||
for (off_t i = 0; i < blocks; i++) {
|
||||
off_t len;
|
||||
if (i == blocks - 1 && src_len % IO_BLOCK_SIZE != 0) {
|
||||
len = src_len % IO_BLOCK_SIZE;
|
||||
} else {
|
||||
len = IO_BLOCK_SIZE;
|
||||
}
|
||||
|
||||
if (read(src_fd, &buf, len) == -1) {
|
||||
perror("read");
|
||||
return -1;
|
||||
};
|
||||
if (write(dst_fd, &buf, len) == -1) {
|
||||
perror("write");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
if (argc != 3) {
|
||||
fprintf(stderr, "usage: %s <src> <dst>\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int src_fd, dst_fd;
|
||||
|
||||
if ((src_fd = open(argv[1], O_RDONLY)) == -1) {
|
||||
perror("open");
|
||||
return 1;
|
||||
}
|
||||
if ((dst_fd = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, 0666)) == -1) {
|
||||
perror("open");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// all necessary files opened, drop filesystem
|
||||
// if (unshare(CLONE_FS) == -1) {
|
||||
// perror("unshare");
|
||||
// return -1;
|
||||
// }
|
||||
|
||||
// fork and copy in a second process
|
||||
pid_t child_pid = fork();
|
||||
if (child_pid == -1) {
|
||||
perror("fork");
|
||||
return -1;
|
||||
} else if (child_pid == 0) {
|
||||
// pause(); // await cgroup setup
|
||||
raise(SIGSTOP); // await cgroup setup
|
||||
return copy(src_fd, dst_fd);
|
||||
}
|
||||
|
||||
// setup a cgroup for the child
|
||||
|
||||
// wait for the child to pause and restart it
|
||||
int status;
|
||||
if (waitpid(child_pid, &status, WUNTRACED | WSTOPPED) == -1) {
|
||||
perror("waitpid");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (WIFSTOPPED(status)) {
|
||||
if (kill(child_pid, SIGCONT) == -1) {
|
||||
perror("kill");
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "child behaved unexpectedly\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// wait for the child process to terminate
|
||||
if (waitpid(child_pid, &status, 0) == -1) {
|
||||
perror("waitpid");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (WIFEXITED(status)) {
|
||||
return WEXITSTATUS(status);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
Reference in New Issue
Block a user