The OpenNET Project / Index page

[ новости /+++ | форум | теги | ]

Каталог документации / Раздел "Программирование, языки" / Оглавление документа

12.2. Процессы не хотят мигрировать!

Помогите, процесс XYZ не мигрирует. Ниже Moshe Bar постарался объяснить, почему одни процессы мигрируют, а другие нет. Тем не менее, предварительно загляните в /proc/$pid/, там может быть файл cantmove, который может подсказать вам, почему же определённый процесс не может мигрировать.

Также процесс может быть просто заблокирован. Чтобы это проверить, посмотрите файл:

cat /proc/$PID/lock

где $PID – это ID проблемного процесса.

А теперь посмотрим что говорит об этом сам Moshe.

Иногда подобные проблемы возникают при использовании одного ядра, но на разных дистрибутивах, к примеру, кластер из смешанных узлов под RedHat или Debian, а rc-скрипты, запускающие на них openMosix, немного различаются. Некоторые версии имеют сильно модифицированный /etc/inittab, запускающий все демоны (и их потомков) при помощи mosrun -h. Таким образом получается, что процессы не могут нормально мигрировать. Следовательно, все эти процессы имеют значение 1 в файле /proc/pid/lock при старте. Но можно заставить их мигрировать, записав 0 в этот файл.

Рассмотрим пример. Есть небольшая программа, которая должна мигрировать, если она запущена в количестве, превышающем количество процессоров на локальной машине. То есть, на двухпроцессорной SMP машине запуск программы в трёх экземплярах заставит её мигрировать, если другие узлы кластера по скорости хотя бы сопоставимы с локальной:

int main() {
	unsigned int i;
	while (1) {
		i++;
	}
	return 0;
}

На процессоре Pentium 800Mhz она достигает переполнения довольно быстро.

А вот, к примеру, подобная программа никогда не будет мигрировать:

#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 */
	...
}

Программы, использующие pthreads версии 2.4.17 и выше, не мигрируют, но, тем не менее, уже и не завершаются аварийно.

//
// 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 – CTO компании Qlusters, Inc.)

Пожалуйста, прочтите также man страницы openMosix, в них также содержится исчерпывающая информация о миграции процессов.

Если по какой-либо причине ваши процессы остаются запертыми, хотя по идее не должны бы, то попробуйте разрешить миграцию запертых процессов, добавив команду

# разрешает подпроцессам мигрировать на другие узлы
echo 0 > /proc/self/lock

в файл /etc/profile.

[Warning]Внимание

Это позволит мигрировать всем процессам, а не тем, которые вы хотите. Для указания миграции определённых процессов используйте утилиту mosrun -l для разблокировки нужного процесса.




Партнёры:
PostgresPro
Inferno Solutions
Hosting by Hoster.ru
Хостинг:

Закладки на сайте
Проследить за страницей
Created 1996-2024 by Maxim Chirkov
Добавить, Поддержать, Вебмастеру