12.2. 我的进程不会迁移

“帮助进程 XYZ 不迁移。” Moshe Bar 在下面解释了为什么有些进程会迁移,而有些进程不会迁移。但在那之前,您可以查看 /proc/$pid/,那里通常有一个 cantmove 文件,它会告诉您为什么某个进程无法迁移。

进程也可能被锁定。您可以使用以下命令检查进程是否被锁定:

cat /proc/$PID/lock
其中 $PID 是相关进程的进程 ID。

现在听听 Moshe 本人对此话题的看法。

通常人们拥有相同的内核,但在不同的发行版上,例如 RedHat 和 Debian 的混合环境,来自不同发行版的 rc 脚本倾向于以不同的方式启动 openmosix。某些实现完全修改 /etc/inittab 以使用以下方式启动所有守护进程(及其子进程):

mosrun -h
。这样它们就不会迁移。因此,当您启动时,所有这些进程在 /proc/pid/lock 中都有一个 1。您可以通过向此文件写入 0 来强制它们迁移。

好的,如果启动次数多于本地 CPU 数量,则这个简单的程序应该始终迁移。因此,对于双路 SMP 系统,如果集群中的其他节点至少具有与本地节点相同的速度,则启动此程序 3 次将开始迁移

int main() {
    unsigned int i;
    while (1) {
        i++;
    }
    return 0;
}
在 Pentium 800Mhz CPU 上,溢出需要相当长的时间。

像这样的示例程序永远不会迁移

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>

...

key_t key; /* key to be passed to shmget() */
int shmflg; /* shmflg to be passed to shmget() */
int shmid; /* return value from shmget() */
int size; /* size to be passed to shmget() */

...

key = ...
size = ...
shmflg) = ...

if ((shmid = shmget (key, size, shmflg)) == -1) {
   perror("shmget: shmget failed"); exit(1); } else {
   (void) fprintf(stderr, "shmget: shmget returned %d\n", shmid);
   exit(0);
  }
...

使用管道的程序可以很好地迁移

int pdes[2];

pipe(pdes);
if ( fork() == 0 )
  { /* child */
                                 close(pdes[1]); /* not required */
                                 read( pdes[0]); /* read from parent */
                                 .....
                 }
else
                 { close(pdes[0]); /* not required */
                                 write( pdes[1]); /* write to child */
                                 .....
                 }
已修改 自 2.4.17 版本以来,使用 pthreads 的程序不会迁移,但它们不再出现段错误。
//
// Very simple program demonstrating the use of threads.
//
// Command-line argument is P (number of threads).
//
// Each thread writes "hello" message to standard output, with
//   no attempt to synchronize.  Output will likely be garbled.
//
#include <iostream>
#include <cstdlib>              // has exit(), etc.
#include <unistd.h>             // has usleep()
#include <pthread.h>            // has pthread_ routines

// declaration for function to be executed by each thread
void * printHello(void * threadArg);

// ---- Main program -------------------------------------------------

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

  if (argc < 2) {
    cerr << "Usage:  " << argv[0] << " numThreads\n";
    exit(EXIT_FAILURE);
  }
  int P = atoi(argv[1]);

  // Set up IDs for threads (need a separate variable for each
  //   since they're shared among threads).
  int * threadIDs = new int[P];
  for (int i = 0; i < P; ++i)
    threadIDs[i] = i;

  // Start P new threads, each with different ID.
  pthread_t * threads = new pthread_t[P];
  for (int i = 0; i < P; ++i)
    pthread_create(&threads[i], NULL, printHello,
                   (void *) &threadIDs[i]);

  // Wait for all threads to complete.
  for (int i = 0; i < P; ++i)
    pthread_join(threads[i], NULL);

  // Clean up and exit.
  delete [] threadIDs;
  delete [] threads;
  cout << "That's all, folks!\n";
  return EXIT_SUCCESS;
}

// ---- Code to be executed by each thread ---------------------------

// pre:  *threadArg is an integer "thread ID".
// post:  "hello" message printed to standard output.
//        return value is null pointer.
void * printHello(void * threadArg) {
  int * myID = (int *) threadArg;
  cout << "hello, world, ";
  // pointless pause, included to make the effects of
  //   synchronization (or lack thereof) more obvious
  usleep(10);
  cout << "from thread " << *myID << endl;
  pthread_exit((void* ) NULL);
}

使用各种文件描述符(包括套接字)的程序会迁移(但是,套接字不会随进程一起迁移,如果使用 oMFS/DFSA,则文件会迁移)

(以上所有代码均由 Moshe 以 Moshe Bar 或 Moshe 以 Qlusters, Inc. 首席技术官的身份编写。)

另请参阅 openMosix 的手册页,它们也充分解释了为什么进程不迁移。

如果由于某种原因,您的进程在不应该锁定的情况下保持锁定状态。您可以尝试通过简单地放入以下内容来允许锁定的进程迁移:

# tell shells to allow subprocs to migrate to other nodes
echo 0 > /proc/self/lock
"/etc/profile" 警告:此修复程序将允许 所有 进程迁移,而不仅仅是您想要的进程。要仅允许特定进程迁移,请使用 'mosrun -l' 来仅解锁所需的进程。