Skip to content

Commit db30d09

Browse files
committed
replace popen with vfork+exec
1 parent e359aac commit db30d09

File tree

2 files changed

+147
-69
lines changed

2 files changed

+147
-69
lines changed

cache_simulator.cpp

+15-64
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ typedef struct {
1919
int enable_fifo;
2020
int enable_lru;
2121
int enable_block;
22+
int enable_block_v2;
2223
} config;
2324

2425
static config g_cfg;
@@ -662,9 +663,9 @@ class CacheStatImpl : public CacheStat {
662663
long last_miss_length_ = 0;
663664
};
664665

665-
class LRUCache : public Cache, public CacheStatImpl {
666+
template <typename Impl> class TCache : public Cache, public CacheStatImpl {
666667
public:
667-
LRUCache(size_t cap)
668+
TCache(size_t cap)
668669
: impl_(cap)
669670
{
670671
}
@@ -690,70 +691,13 @@ class LRUCache : public Cache, public CacheStatImpl {
690691
}
691692

692693
private:
693-
LRUCacheImpl<string> impl_;
694+
Impl impl_;
694695
};
695696

696-
class FIFOCache : public Cache, public CacheStatImpl {
697-
public:
698-
FIFOCache(size_t cap)
699-
: impl_(cap)
700-
{
701-
}
702-
703-
void get(const string &key, const size_t length) override
704-
{
705-
auto [is_hit, old_length] = impl_.get(key);
706-
if (!is_hit || old_length != length) {
707-
is_hit = false;
708-
impl_.set(key, length);
709-
}
710-
on_get(key, length, is_hit);
711-
}
712-
713-
Stat get_stat() const override
714-
{
715-
Stat stat;
716-
stat.class_name = get_filt_type_name<decltype(*this)>();
717-
stat.capacity = impl_.capacity();
718-
stat.count = impl_.count();
719-
stat.used = impl_.used();
720-
return stat;
721-
}
722-
723-
private:
724-
FIFOCacheImpl<string> impl_;
725-
};
726-
727-
class BlockCache : public Cache, public CacheStatImpl {
728-
public:
729-
BlockCache(size_t cap)
730-
: impl_(cap)
731-
{
732-
}
733-
734-
void get(const string &key, const size_t length) override
735-
{
736-
auto [is_hit, old_length] = impl_.get(key);
737-
if (!is_hit || old_length != length) {
738-
is_hit = false;
739-
impl_.set(key, length);
740-
}
741-
on_get(key, length, is_hit);
742-
}
743-
744-
Stat get_stat() const override
745-
{
746-
Stat stat;
747-
stat.class_name = get_filt_type_name<decltype(*this)>();
748-
stat.capacity = impl_.capacity();
749-
stat.count = impl_.count();
750-
stat.used = impl_.used();
751-
return stat;
752-
}
753-
754-
private:
755-
BlockCacheImpl<string> impl_;
756-
};
697+
using LRUCache = TCache<LRUCacheImpl<string>>;
698+
using FIFOCache = TCache<FIFOCacheImpl<string>>;
699+
using BlockCache = TCache<BlockCacheImpl<string>>;
700+
using BlockCacheV2 = TCache<BlockCacheImplV2<string>>;
757701

758702
vector<string> split(const string &str, const string &delim)
759703
{
@@ -774,6 +718,7 @@ vector<string> split(const string &str, const string &delim)
774718
LRUCache *g_lru_cache = nullptr;
775719
FIFOCache *g_fifo_cache = nullptr;
776720
BlockCache *g_block_cache = nullptr;
721+
BlockCacheV2 *g_block_cache_v2 = nullptr;
777722

778723
static void cache_get(const string &key, const long len)
779724
{
@@ -790,6 +735,10 @@ static void cache_get(const string &key, const long len)
790735
if (g_cfg.enable_block) {
791736
g_block_cache->get(key, len);
792737
}
738+
739+
if (g_cfg.enable_block_v2) {
740+
g_block_cache_v2->get(key, len);
741+
}
793742
}
794743

795744
static void process_line(const string &line)
@@ -855,6 +804,7 @@ static command_t cmds[] = { { "c", "cap", cmd_set_size, offsetof(config, capacit
855804
{ "", "fifo", cmd_set_bool, offsetof(config, enable_fifo), "on" },
856805
{ "", "lru", cmd_set_bool, offsetof(config, enable_lru), "on" },
857806
{ "", "block", cmd_set_bool, offsetof(config, enable_block), "on" },
807+
{ "", "block_v2", cmd_set_bool, offsetof(config, enable_block_v2), "on" },
858808
{ "", "v2", nullptr, offsetof(config, is_v2), nullptr, "" } };
859809

860810
int main(int argc, const char *argv[])
@@ -869,6 +819,7 @@ int main(int argc, const char *argv[])
869819
g_lru_cache = new LRUCache(g_cfg.capacity);
870820
g_fifo_cache = new FIFOCache(g_cfg.capacity);
871821
g_block_cache = new BlockCache(g_cfg.capacity);
822+
g_block_cache_v2 = new BlockCacheV2(g_cfg.capacity);
872823

873824
for (string line; std::getline(std::cin, line);) {
874825
if (g_cfg.is_v2) {

util.h

+132-5
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ extern "C" {
2828
#include <sys/stat.h>
2929
#include <sys/time.h>
3030
#include <sys/types.h>
31+
#include <sys/wait.h>
3132
#include <time.h>
3233
#include <unistd.h>
3334
#include <signal.h>
@@ -665,12 +666,8 @@ time_format(char *buf, size_t cap, time_t now)
665666
}
666667

667668
static int
668-
read_command_output(const char *command, char *buf, size_t n)
669+
read_command_output_popen(const char *command, char *buf, size_t n)
669670
{
670-
if (buf == NULL || n == 0) {
671-
return -2;
672-
}
673-
674671
FILE *pipe = popen(command, "r");
675672
if (pipe == NULL) {
676673
return -1;
@@ -697,6 +694,136 @@ read_command_output(const char *command, char *buf, size_t n)
697694
return 0;
698695
}
699696

697+
static char **
698+
split_cstring(const char *str, const char *sep)
699+
{
700+
if (str_empty(str) || str_empty(sep)) {
701+
return NULL;
702+
}
703+
704+
char *dupped_str = strdup(str);
705+
size_t lenstr = strlen(dupped_str);
706+
str = dupped_str;
707+
char **arr = (char **)malloc(sizeof(char *) * (lenstr + 1));
708+
char *token = NULL;
709+
char *ptr = NULL;
710+
int n = 0;
711+
712+
while ((token = strtok_r((char *)str, sep, &ptr)) != NULL) {
713+
str = NULL;
714+
arr[n++] = strdup(token);
715+
}
716+
717+
arr[n] = NULL;
718+
free(dupped_str);
719+
720+
return arr;
721+
}
722+
723+
static void
724+
do_read_from_fd(int fd, char *buf, size_t n)
725+
{
726+
if (n > 0) {
727+
buf[0] = '\0';
728+
}
729+
730+
while (n > 1) {
731+
buf[0] = '\0';
732+
733+
int nr = read(fd, buf, n - 1);
734+
if (nr > 0) {
735+
buf[nr] = '\0';
736+
buf += nr;
737+
n -= nr;
738+
}
739+
740+
if (nr <= 0) {
741+
break;
742+
}
743+
}
744+
}
745+
746+
static int
747+
read_command_output_impl_2(char **arr, char *buf, size_t n, int fds[2])
748+
{
749+
int r = fds[0];
750+
int w = fds[1];
751+
int saved_errno = 0;
752+
753+
pid_t pid = vfork();
754+
if (pid < 0) {
755+
return -1;
756+
}
757+
758+
if (pid == 0) {
759+
// child process
760+
close(r);
761+
762+
// redirect stdout and stderr to fd w
763+
if (dup2(w, 1) < 0 || dup2(w, 2) < 0) {
764+
saved_errno = errno;
765+
_Exit(0);
766+
}
767+
768+
if (execvp(arr[0], arr) < 0) {
769+
saved_errno = errno;
770+
_Exit(1);
771+
}
772+
} else {
773+
// parent, read output from fd r
774+
int dup_ret = dup2(r, w);
775+
if (dup_ret >= 0) {
776+
do_read_from_fd(r, buf, n);
777+
}
778+
779+
waitpid(pid, NULL, 0);
780+
781+
if (dup_ret < 0) {
782+
return -1;
783+
}
784+
}
785+
786+
return 0;
787+
}
788+
789+
static int
790+
read_command_output_impl_1(const char *command, char *buf, size_t n, int fds[2])
791+
{
792+
char **arr = split_cstring(command, " ");
793+
if (arr == NULL) {
794+
return -1;
795+
}
796+
797+
int rc = read_command_output_impl_2(arr, buf, n, fds);
798+
799+
for (int i = 0; arr[i] != NULL; i++) {
800+
free(arr[i]);
801+
}
802+
free(arr);
803+
804+
return rc;
805+
}
806+
807+
static int
808+
read_command_output(const char *command, char *buf, size_t n)
809+
{
810+
if (buf == NULL || n == 0) {
811+
return -2;
812+
}
813+
814+
int fds[2];
815+
if (pipe(fds) < 0) {
816+
return -1;
817+
}
818+
819+
int rc = read_command_output_impl_1(command, buf, n, fds);
820+
821+
close(fds[0]);
822+
close(fds[1]);
823+
824+
return rc;
825+
}
826+
700827
typedef struct URI URI;
701828

702829
struct URI {

0 commit comments

Comments
 (0)