LINUX.ORG.RU

Сообщения leonopulos

 

Очередь сообщений с ожиданием нового сообщения в ядре по типу select()

Форум — Development

Пишу приложение, в котором обмен сообщениями между несколькими потоками я собираюсь организовать при помощи очередей сообщений. При чем каждый поток должен ожидать сообщения от нескольких потоков одновременно. То есть, алгоритм ожидания событий должен быть полностью идентичен алгоритму ожидания событий в select(). Сами очереди событий буду писать сам, объектами SysV пользоваться не буду, так как мне не нужно взаимодействие между процессами. Проблема в том, что все алгоритмы, реализации которых мне удалось найти предлагают различные варианты с периодическим опросом и ожиданием, типа sleep(). Но в них присутствует задержка на обработку событий и бессмысленное периодическое просыпание потоков для проверки. Есть ли вариант реализации без этих дефектов? Прошу помощи с информацией.

 ,

leonopulos
()

Контроллер RS-232 PCIe с драйверами под Linux

Форум — Linux-hardware

У меня встал вопрос выбора контроллера COM-порта под шину PCIe с хорошими драйверами под Linux Debian. Посоветуйте, пожалуйста, что-нибудь. На маркетплейсах нашел только девайсы с чипами от WCH. Типа CH382. Попробовал драйвера скомпилировать перед покупкой - они не компилятся. Кто чем пользуется, посоветуйте, плиз, что-нибудь рабочее.

 , ,

leonopulos
()

Совместное использование одного UDP порта двумя сокетами

Форум — Development

Суть проблемы в следующем. По порту приходит смешанный поток данных: RTP поток и команды от оборудования. В своей программе я создал 2 потока и в обоих потоках ловлю события от порта при помощи select(). Вот настройка первого потока, который должен вылавливать RTP из порта: select() задается вполне стандартно:

select(n, readfds, writefds,exceptfds, p_timeout);

При создании сокета добавляю SO_REUSEADDR:

*sock = socket(af, SOCK_DGRAM, IPPROTO_UDP);
if (*sock == -1)
  return RETURN_ERROR(get_native_netos_error());
  else {
    int32_t val = 1;
    sock_setsockopt(*sock, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));

2й сокет в другом потоке открывается также, как и первый и тоже биндится без ошибок:

if ((s = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
  return -1;
  }
yes = 1;

if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (uint8 *) &yes, sizeof (yes)) < 0) {
        close (s);
        return -1;
    }

Оба сокета открываются, у обоих положительные дескрипторы, но сообщения приходят только на один сокет почему-то. Хотя я на нем читаю эти сообщения с флагом MSG_PEEK специально, чтобы эти же сообщения оставлять для второго сокета, который для RTP предназначен, но этого почему-то не происходит:

len = recvfrom(serv, &req[0], 128, MSG_PEEK,(struct sockaddr *) &rem_serv, &serv_from_len);
if (bytes_parse(req, len, &my_struct) != P_SUCCESS)
	return P_FAILURE;
len = recvfrom(serv, &req[0], len, 0,(struct sockaddr *) &rem_serv, &serv_from_len);

То есть, 1-м recvfrom читаю сообщение и оставляю его в буфере, если это команда (не RTP), я его читаю еще раз, чтобы удалить из буфера, а если RTP, то просто выхожу из обработчика и его, по идее, должен как раз 2-й поток прочитать, но этого не происходит. Помогите, кто чем может.

 , ,

leonopulos
()

Сборка стороннего проекта в Qt MinGW

Форум — Development

Вопрос в следующем. Есть сторонний проект, который собирается configure и make. Библиотеки этого проекта я затем использую в своей программе под Qt. Как мне собрать этот проект тем же комплектом MinGW из Qt, чтобы избежать конфликтов?

 , ,

leonopulos
()

Настройка шлюза strongSWAN + iptables + tightvncserver

Форум — Admin

У меня есть 2 удалённых сервера. На одном из них работает tightvncserver со своими десктопными задачами. Сервер сидит на localhost, а доступ к нему организован через ssh туннель. Есть так же 2-й сервер, на котором я организовал VPN-сервер силами strongSWAN и iptables. Иметь в наше время 2 удалённых сервера - непомерная роскошь, и я задумываюсь, как бы объединить оба сервера в один. То есть, как бы реализовать следующую задачу: Есть приватная сеть, в которую входят мои устройства и tightvncserver на удалённом сервере, который доступен только из этой приватной сети, и этот же шлюз работает, как обычный VPN-шлюз в интернет. Читаю документацию, смотрю примеры реализации, но пока не могу понять, как это можно реализовать? Прошу помощи в понимании вопроса.

 , , ,

leonopulos
()

Непонятная ошибка распределения памяти

Форум — Development

Здравствуйте, уважаемые форумчане.

Столкнулся с очень странной ошибкой в алгоритме декодирования Base64.Во время работы алгоритма магическим образом на 4-й итерации цикла затирается внутренняя переменная unsigned long outmax. При чем эта ошибка проявляется только на 32-ных реализациях. Скомпилировал код под 64 бита - всё нормально. Подозреваю, что как-то HEAP портится, но не могу понять - как. Прошу помощи. Вот полный код программы с алгоритмом:

#include <string.h>
#include <stdarg.h>

#include <ctype.h>
#include <stdlib.h>

static int
xmlBase64Decode(const unsigned char *in, unsigned long *inlen,
	        unsigned char *to, unsigned long *tolen) {
    unsigned long incur;		/* current index in in[] */
    unsigned long inblk;		/* last block index in in[] */
    unsigned long outcur;		/* current index in out[] */
    unsigned long inmax;		/* size of in[] */
    unsigned long outmax;		/* size of out[] */
    unsigned char cur;			/* the current value read from in[] */
    unsigned char intmp[3], outtmp[4];	/* temporary buffers for the convert */
    int nbintmp;			/* number of byte in intmp[] */
    int is_ignore;			/* cur should be ignored */
    int is_end = 0;			/* the end of the base64 was found */
    int retval = 1;
    int i;

    if ((in == NULL) || (inlen == NULL) || (to == NULL) || (tolen == NULL))
	return(-1);

    incur = 0;
    inblk = 0;
    outcur = 0;
    inmax = *inlen;
    outmax = *tolen;
    nbintmp = 0;

    while (1) {
        if (incur >= inmax)
            break;
        cur = in[incur++];
        is_ignore = 0;
        if ((cur >= 'A') && (cur <= 'Z'))
            cur = cur - 'A';
        else if ((cur >= 'a') && (cur <= 'z'))
            cur = cur - 'a' + 26;
        else if ((cur >= '0') && (cur <= '9'))
            cur = cur - '0' + 52;
        else if (cur == '+')
            cur = 62;
        else if (cur == '/')
            cur = 63;
        else if (cur == '.')
            cur = 0;
        else if (cur == '=') /*no op , end of the base64 stream */
            is_end = 1;
        else {
            is_ignore = 1;
	    if (nbintmp == 0)
		inblk = incur;
	}

        if (!is_ignore) {
            int nbouttmp = 3;
            int is_break = 0;

            if (is_end) {
                if (nbintmp == 0)
                    break;
                if ((nbintmp == 1) || (nbintmp == 2))
                    nbouttmp = 1;
                else
                    nbouttmp = 2;
                nbintmp = 3;
                is_break = 1;
            }
            intmp[nbintmp++] = cur;
	    /*
	     * if intmp is full, push the 4byte sequence as a 3 byte
	     * sequence out
	     */
            if (nbintmp == 4) {
                nbintmp = 0;
                outtmp[0] = (intmp[0] << 2) | ((intmp[1] & 0x30) >> 4);
                outtmp[1] =
                    ((intmp[1] & 0x0F) << 4) | ((intmp[2] & 0x3C) >> 2);
                outtmp[2] = ((intmp[2] & 0x03) << 6) | (intmp[3] & 0x3F);
		if (outcur + 3 >= outmax) {
		    retval = 2;
		    break;
		}

                for (i = 0; i < nbouttmp; i++)
		    to[outcur++] = outtmp[i];
		inblk = incur;
            }

            if (is_break) {
		retval = 0;
                break;
	    }
        }
    }

    *tolen = outcur;
    *inlen = inblk;
    return (retval);
}


int main (void){
	const unsigned char *in_buf = "ABUACwEAAAYAHQAAAAm0BQMAAAEAAAMA";
	unsigned long in_len = strlen(in_buf);
	unsigned long out_len = (in_len * 6) / 8;
	unsigned char *out_buf = NULL;
	out_buf = malloc(out_len);
	if (out_buf != NULL){
		memset(out_buf, 0, out_len);
		xmlBase64Decode((const unsigned char *)in_buf,(unsigned long *) &in_len, (unsigned char *) out_buf,(unsigned long *) &out_len);
	}
	if (out_len != 0)
    {
    	int i;
    	char *prn_buf = NULL;
    	char temp_buf[3];
    	int prn_buf_len = out_len * 3 + 1;
    	prn_buf = malloc(prn_buf_len);
    	if (prn_buf != NULL){
    		memset(prn_buf, 0, prn_buf_len);
    		for (i = 0; i < out_len; i++){
    			sprintf(&temp_buf[0], " %.2X", out_buf[i]);
    			prn_buf[i * 3] = temp_buf[0];
    			prn_buf[i * 3 + 1] = temp_buf[1];
    			prn_buf[i * 3 + 2] = temp_buf[2];
    		}
    		prn_buf[out_len * 3] = 0;
    		printf("Packet = [%s]", prn_buf);
    		free(prn_buf);
    	}
    }
}

 , ,

leonopulos
()

Проблема с bind-ингом UDP порта

Форум — Development

Добрый вечер. Не пойму, почему моя программа не может получить доступ к UDP порту. В лог-файлах пишет следующее:

Jun 18 18:01:17 myserver mydaemon0[3904]: bind error for udp error string: 'Address already in use'
Jun 18 18:01:17 myserver mydaemon0[3904]: not binding to 4005 port

смотрю, что выдаёт netstat:

root@myserver:~# netstat -atulpn
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:111 0.0.0.0:* LISTEN 1754/rpcbind
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 2495/sshd
tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN 3130/exim4
tcp 0 0 127.0.0.1:3306 0.0.0.0:* LISTEN 2749/mysqld
tcp 0 0 0.0.0.0:37322 0.0.0.0:* LISTEN 1807/rpc.statd
tcp 0 0 192.168.0.99:22 192.168.0.130:54276 ESTABLISHED 2780/0
tcp6 0 0 :::111 :::* LISTEN 1754/rpcbind
tcp6 0 0 :::8080 :::* LISTEN 2249/apache2
tcp6 0 0 :::80 :::* LISTEN 2249/apache2
tcp6 0 0 :::22 :::* LISTEN 2495/sshd
tcp6 0 0 ::1:25 :::* LISTEN 3130/exim4
tcp6 0 0 :::44730 :::* LISTEN 1807/rpc.statd
tcp6 0 0 192.168.0.99:80 192.168.0.130:44882 TIME_WAIT -
tcp6 0 0 192.168.0.99:80 192.168.0.130:44881 TIME_WAIT -
tcp6 0 0 192.168.0.99:80 192.168.0.130:44883 ESTABLISHED 2899/apache2
udp 0 0 0.0.0.0:68 0.0.0.0:* 1850/dhclient
udp 0 0 0.0.0.0:68 0.0.0.0:* 1848/dhclient
udp 0 0 0.0.0.0:111 0.0.0.0:* 1754/rpcbind
udp 0 0 0.0.0.0:657 0.0.0.0:* 1754/rpcbind
udp 0 0 0.0.0.0:65209 0.0.0.0:* 1848/dhclient
udp 0 0 127.0.0.1:711 0.0.0.0:* 1807/rpc.statd
udp 0 0 0.0.0.0:43207 0.0.0.0:* 1850/dhclient
udp 0 0 0.0.0.0:49897 0.0.0.0:* 1807/rpc.statd
udp6 0 0 :::32813 :::* 1807/rpc.statd
udp6 0 0 :::111 :::* 1754/rpcbind
udp6 0 0 :::657 :::* 1754/rpcbind
udp6 0 0 :::65209 :::* 1850/dhclient
udp6 0 0 :::11527 :::* 1848/dhclient

и вижу, что нигде мой порт не встречается. правда, в выводе netstata я не вижу записей с нужного мне интерфейса - на сервере их 3:

root@myserver:~# route
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
default readynas.netgea 0.0.0.0 UG 0 0 0 eth0
192.168.0.0 * 255.255.255.0 U 0 0 0 eth0
192.168.10.0 * 255.255.255.0 U 0 0 0 eth5
192.168.11.0 * 255.255.255.0 U 0 0 0 eth6

Я пытаюсь открыть UDP порты 4005 на 192.168.10.0 и на 192.168.11.0 и получаю 'Address already in use' Подскажите, пожалуйста, в чём может быть проблема?

 , ,

leonopulos
()

Не блокируется pid-файл

Форум — Development

Здравствуйте. Отлаживаю свой демон. Перевод в режим демона делаю по книге «UNIX Профессиональное программирование Второе издание У. Ричард Стивенс, Стивен А. Раго»

как-то так:

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

...

// Перейти в режим демона.

daemonize(daemon_name);

// Убеждаемся, что нет запущенной копии

if (already_running(daemon_name, &fd_lock)) {

my_log(LOG_ERR, «daemon already running»);

return EXIT_FAILURE;

}

// Запуск рабочего тела демона

daemon(daemon_name);

// Закрываем файл, снимаем блокировку

close(fd_lock);

return EXIT_SUCCESS

}

void daemonize(const char *daemoName)

{

int i, fd0, fd1, fd2;

pid_t pid;

struct rlimit rl;

struct sigaction sa;

/*

** Сбросить маску режима создания файла.

*/

umask(0);

/*

* Получить максимально возможный номер дескриптора файла.

*/

if (getrlimit(RLIMIT_NOFILE, &rl) < 0)

err_quit(«%s: impossible to obtain the maximum number of descriptors.», daemoName);

/*

* Стать лидером новой сессии, чтобы утратить управляющий терминал.

*/

if ((pid = fork()) < 0)

err_quit(«%s: error function call fork», daemoName);

else if (pid != 0) /* родительский процесс */

exit(0);

setsid();

/*

* Обеспечить невозможность обретения управляющего терминала в будущем.

*/

sa.sa_handler = SIG_IGN;

sigemptyset(&sa.sa_mask);

sa.sa_flags = 0;

if (sigaction(SIGHUP, &sa, NULL) < 0)

err_quit(«%s: impossible to ignore the SIGHUP signal»);

if ((pid = fork()) < 0)

err_quit(«%s: error function call fork», daemoName);

else if (pid != 0) /* родительский процесс */

exit(0);

/*

* Назначить корневой каталог текущим рабочим каталогом,

* чтобы впоследствии можно было отмонтировать файловую систему.

*/

if (chdir(«/») < 0)

err_quit(«%s: impossible to make the current working directory /»);

/*

* Закрыть все открытые файловые дескрипторы.

*/

if (rl.rlim_max == RLIM_INFINITY)

rl.rlim_max = 1024;

for (i = 0; i < rl.rlim_max; i++)

close(i);

/*

* Присоединить файловые дескрипторы 0, 1 и 2 к /dev/null.

*/

fd0 = open(«/dev/null», O_RDWR);

fd1 = dup(0);

fd2 = dup(0);

if (fd0 != 0 || fd1 != 1 || fd2 != 2) {

my_log(LOG_ERR, «wrong file descriptors %d %d %d», fd0, fd1, fd2);

exit(1);

}

}

int already_running(const char *daemoName, int *fd_lock)

{

int fd;

char buf[16];

char *pathname;

#define LOCKMODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)

pathname = malloc(32);

memset(pathname, 0, 32);

sprintf(pathname,«/var/run/%s.pid»,daemoName);

fd = open(pathname, O_RDWR|O_CREAT, LOCKMODE);

if (fd < 0) {

printf(«do not open %s: %s\n», pathname, strerror(errno));

exit(1);

}

if (lockfile(fd) < 0) {

if (errno == EACCES || errno == EAGAIN) {

close(fd);

return(1);

}

printf(«do not set lock on %s: %s\n», pathname, strerror(errno));

exit(1);

}

ftruncate(fd, 0);

sprintf(buf, «%ld», (long)getpid());

write(fd, buf, strlen(buf));

// файл не закрывается, пока демон запущен.

*fd_lock = fd;

return(0);

}

int lockfile(int fd)

{

struct flock fl;

fl.l_type = F_WRLCK;

fl.l_start = 0;

fl.l_whence = SEEK_SET;

fl.l_len = 0;

return(fcntl(fd, F_SETLK, &fl));

}

Вроде бы already_running запускается после daemonize, то есть после fork-а и после закрытия вех дескрипторов, но pid-файлы всё равно остаются не заблокированными на запись. Что может быть? Подскажите.

 ,

leonopulos
()

RSS подписка на новые темы