我正在编写一个程序来解决操作系统概念一书中的练习。这个问题是在子进程上创建一个Collatz猜想,并使用Posix共享内存将其打印回父进程。这是我的计划。
int main(int argc, char* argv[])
{
const char* name = "Collatz";
const int SIZE = 4096 * 30;
void *ptr;
int shm_fd;
int num = atoi(argv[1]);
pid_t pid;
shm_fd = shm_open(name, O_CREAT | O_RDWR, 0666);
ftruncate(shm_fd, SIZE);
ptr = mmap(0, SIZE, PROT_READ, MAP_SHARED, shm_fd, 0);
if (ptr < 0) perror("Ptr error");
pid = fork();
if (pid < 0) perror("Fork Failed");
else if (pid == 0) {
shm_fd = shm_open(name, O_RDWR, 0666);
ptr = mmap(0, SIZE, PROT_WRITE, MAP_SHARED, shm_fd, 0);
if (ptr < 0) perror("Ptr error");
while (num != 1) {
sprintf(ptr, "%d", num);
ptr++;
if (num % 2 == 0) num /= 2;
else num = 3 * num + 1;
}
sprintf(ptr, "%d", num);
ptr++;
} else {
wait(NULL);
printf("Parent: %s\n", (char*) ptr);
//ptr += sizeof(int);
shm_unlink(name);
}
return 0;
}
但是当我用 gcc 编译它时,我得到分段错误(核心转储)。虽然搜索谷歌,但我不知道它。我使用Ubuntu 14.04。有人可以帮助我。非常感谢,抱歉我的英语不好。
答案 0 :(得分:2)
我尝试使用以下包含编译您的代码,它对我有用。
./collatz 12
你有没有想过在执行程序时传递一个整数参数? (例如)
CREATE TABLE IF NOT EXISTS `configuration_changed` (
`table_name` TEXT(30) NOT NULL,
`column_name` VARCHAR(45) NULL,
`idbox` INT(11) UNSIGNED NOT NULL,
`pk` TEXT NOT NULL,
`old_value` VARCHAR(45) NULL,
`new_value` VARCHAR(45) NULL,
`date` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
`type` ENUM('NEW','DELETE','CHANGE') NULL,
INDEX `FK_conf_changed_idbox_idx` (`idbox` ASC),
CONSTRAINT `FK_conf_changed_idbox`
FOREIGN KEY (`idbox`)
REFERENCES `box` (`id`)
ON DELETE CASCADE
ON UPDATE RESTRICT)
输出1631518421
答案 1 :(得分:0)
这是我的解决方案,希望对您有所帮助。共享内存通过系统功能mmap(2)加载到进程的后面。
void ∗ mmap (void ∗ addr, size_t len, int prot, int flags, int fd, off_t offset);
参数为:
•addr-要加载到进程中的地址(通常在这里我们使用0来让内核决定加载位置)
•加载的内存大小•Prot-访问权限(通常为PROTREAD或PROTWRITE)
•标志-内存类型(通常为MAPSHARED,以便其他人可以看到该进程所做的更改)
•fd-内存对象的描述符
•offset-共享内存对象中的位置,将从中重播该位置。
成功执行后,结果是指向对象已加载到的进程空间中地址的指针。否则,将返回MAPFAILED值,并将errno设置为适当的值。
请注意,在Linux中,大小必须是页面的倍数:PAGE_SIZE(为此,我使用了getpagesize(2))
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/mman.h>
#include <sys/sysmacros.h>
int main(int argc, char *argv[])
{
fprintf(stdout, "Starting parent %d\n", getpid());
int wstatus, shm_fd;
char shm_name[] = "collatz";
struct stat sb;
pid_t pid;
unsigned int displacement = 0, offset = 0;
size_t shm_size = getpagesize() * (argc - 1);
if(argc < 2)
{
fprintf(stderr, "At least one argument must be passed!");
exit(EXIT_FAILURE);
}
int *pid_children = (int*)malloc((argc - 1) * sizeof(int));
if(pid_children == NULL)
{
fprintf(stderr, "Memory not allocated!");
exit(1);
}
/* Create shared memory object */
shm_fd = shm_open(shm_name, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
if(shm_fd < 0)
{
perror(NULL);
return errno;
}
/* Define size */
if(ftruncate(shm_fd, shm_size) == -1) {
perror(NULL);
shm_unlink(shm_name);
return errno;
}
for(int i = 1; i < argc; i ++)
{
int n = atoi(argv[i]), aux = atoi(argv[i]);
if(n < 0)
{
fprintf(stderr, "Only positive numbers!\n");
i = i + 1;
}
pid_children[i - 1] = fork();
if(pid_children[i - 1] < 0)
return errno;
if(pid_children[i - 1] == 0)
{
/* Child instructions */
char *shm_ptr_child = mmap(0, getpagesize(), PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, (i - 1) * getpagesize());
if(shm_ptr_child == MAP_FAILED)
{
perror(NULL);
shm_unlink(shm_name);
return errno;
}
int count = 0;
int *series = (int*)malloc(count * sizeof(int));
if(series == NULL)
{
fprintf(stderr, "Memory allocation error!");
exit(1);
}
*(series + count) = n;
while(n != 1)
{
count = count + 1;
series = (int*)realloc(series, (count + 1) * sizeof(int));
if(series == NULL)
{
fprintf(stderr, "Memory allocation failure!");
free(series);
exit(EXIT_FAILURE);
}
if(n % 2== 0)
n = n / 2;
else
n = 3 * n + 1;
*(series + count) = n;
}
if(n == 1){
offset = sprintf(shm_ptr_child, "%d : ", aux);
shm_ptr_child += offset;
for(int i = 0; i < count + 1; i++)
{
offset = sprintf(shm_ptr_child, "%d ", series[i]);
shm_ptr_child += offset;
}
free(series);
munmap(shm_ptr_child, getpagesize());
fprintf(stdout, "Done Parent: %d, Me: %d \n", getppid(), getpid());
exit(EXIT_SUCCESS);
}
else
exit(EXIT_FAILURE);
}
else{
/* Parent instructions */
do{
pid = waitpid(pid_children[i - 1], &wstatus, WUNTRACED | WCONTINUED);
if(pid == -1)
{
perror("waitpid");
return -1;
}
if(WIFEXITED(wstatus)){
fprintf(stdout, "exited, status = %d\n", WEXITSTATUS(wstatus));
}else if(WIFSIGNALED(wstatus)) {
fprintf(stdout, "killed by the signal: %d\n", WTERMSIG(wstatus));
}else if(WIFSTOPPED(wstatus)) {
fprintf(stdout, "stopped by the signal %d\n", WSTOPSIG(wstatus));
}else if(WIFCONTINUED(wstatus)) {
fprintf(stdout, "continued\n");
}
}while(!WIFEXITED(wstatus) && !WIFSIGNALED(wstatus));
}
}
for(int i = 0; i < argc - 1; i++)
{
char *shm_ptr = mmap(0, getpagesize(), PROT_READ, MAP_SHARED, shm_fd, i * getpagesize());
fprintf(stdout, "%s\n", shm_ptr);
munmap(shm_ptr, getpagesize());
}
shm_unlink(shm_name);
printf("\nDone Parent: %d, Children: %d \n", getppid(), getpid());
return 0;
}